package com.zuipin.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zuipin.entity.DeliveryAddress;
import com.zuipin.entity.MemberAccount;
import com.zuipin.entity.MemberLevel;
import com.zuipin.entity.OrderInfo;
import com.zuipin.entity.RedPacket;
import com.zuipin.entity.RuleSetUseLog;
import com.zuipin.entity.product.ProductExtInfo;
import com.zuipin.entity.product.ProductInfo;
import com.zuipin.entity.product.ProductPrice;
import com.zuipin.entity.shoppingCart.CartParam;
import com.zuipin.entity.shoppingCart.CartProInfo;
import com.zuipin.entity.shoppingCart.Gift;
import com.zuipin.entity.shoppingCart.ProRuleSet;
import com.zuipin.entity.shoppingCart.RuleSet;
import com.zuipin.entity.shoppingCart.RuleType;
import com.zuipin.entity.shoppingCart.ShoppingCart;
import com.zuipin.entity.shoppingCart.ShowType;
import com.zuipin.entity.shoppingCart.Status;
import com.zuipin.enums.BusinessType;
import com.zuipin.enums.InvoiceType;
import com.zuipin.enums.PayType;
import com.zuipin.enums.PremiumEnum;
import com.zuipin.enums.RedPackStatus;
import com.zuipin.framework.emuns.ErrorCode;
import com.zuipin.framework.exception.CustomException;
import com.zuipin.framework.result.Result;
import com.zuipin.mapper.ProRuleSetMapper;
import com.zuipin.mapper.RuleSetMapper;
import com.zuipin.mapper.ShoppingCartMapper;
import com.zuipin.service.IDeliveryAddressService;
import com.zuipin.service.IIntegralRecordService;
import com.zuipin.service.IMemberAccountService;
import com.zuipin.service.IMemberLevelService;
import com.zuipin.service.IPayOrderService;
import com.zuipin.service.IProductExtInfoService;
import com.zuipin.service.IProductInfoService;
import com.zuipin.service.IProductPriceService;
import com.zuipin.service.IRedPacketService;
import com.zuipin.service.IRuleSetService;
import com.zuipin.service.IShoppingCartService;
import com.zuipin.util.ArithUtil;
import com.zuipin.util.ConstantsUtil;
import com.zuipin.util.DateUtils;
import com.zuipin.util.HttpUtil;
import com.zuipin.util.StringUtil;
import com.zuipin.vo.BackOrderDetailVo;
import com.zuipin.vo.CheckRuleSetParam;
import com.zuipin.vo.CheckRuleSetResult;
import com.zuipin.vo.FrontOrderDetailVo;
import com.zuipin.vo.FrontOrderVo;
import com.zuipin.vo.ImgAndTitlePro;
import com.zuipin.vo.OrderBuyAgainVo;
import com.zuipin.vo.OrderDetailVo;
import com.zuipin.vo.PayOrderVo;
import com.zuipin.vo.ProExtInfoVo;
import com.zuipin.vo.ProExtSerachVo;
import com.zuipin.vo.ProductExtVo;
import com.zuipin.vo.RedPacketVo;
import com.zuipin.vo.UseRuleSetVo;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * @description : 购物车实现
 * @author : wuhaijun
 * @date : 2017年3月28日 下午2:41:55
 */
@Service
public class ShoppingCartServiceImpl implements IShoppingCartService {
	
	@Autowired
	private RuleSetMapper			ruleSetMapper;
	
	@Autowired
	private ShoppingCartMapper		shoppingCartMapper;
	
	@Autowired
	private IDeliveryAddressService	deliveryAddressService;
	
	@Autowired
	private IRedPacketService		redPacketService;
	
	@Autowired
	private IMemberLevelService		memberLevelService;
	
	@Autowired
	private IMemberAccountService	memberAccountService;
	
	@Autowired
	private IPayOrderService		payOrderService;
	
	@Autowired
	private IProductInfoService		productInfoService;
	
	@Autowired
	private IIntegralRecordService	integralRecordService;
	
	@Autowired
	private IRuleSetService			ruleSetService;
	
	@Autowired
	private ProRuleSetMapper		proRuleSetMapper;
	
	@Value("${cis.findBranchStockUrl}")
	private String					findBranchStockUrl;
	
	@Autowired
	private IProductExtInfoService	proExtInfoService;
	
	@Autowired
	private IProductPriceService	productPriceService;
	
	// 等待传入的接口
	// private Myservice myservice;
	
	private final static Logger		log		= LoggerFactory.getLogger(ShoppingCartServiceImpl.class);
	
	// 常量定义
	private final static String		TITLE	= "TITLE";
	private final static String		PRO_SKU	= "PRO_SKU";
	private final static String		IMG_URL	= "IMG_URL";
	private final static String		STATE	= "STATE";
	
	/**
	 * @description : 根据规则获取特价商品
	 * @author : wuhaijun
	 * @date : 2017年4月26日 上午11:22:49
	 */
	private ProRuleSet getSpecialPricePro(Long sysId, String device, String proSku) {
		String currTime = DateUtils.getCurrentDateTime();
		RuleSet ruleSet = ruleSetMapper.querySpecialPriceRule(sysId, device, currTime, proSku);
		if (ruleSet == null) {
			return null;
		}
		return ruleSetMapper.querySpecialPricePro(proSku, ruleSet.getId());
	}
	
	/**
	 * @description : 获取商品名称、价格等信息
	 * @author : wuhaijun
	 * @date : 2017年4月26日 上午8:54:30
	 */
	@Override
	public CartProInfo getProInfo(Long proId, String proSku, Long sysId, Long memberId, String device, BigDecimal buyNum, boolean isPremium) throws CustomException {
		boolean isLogin = memberId == null ? false : true;
		ProductExtVo productExtVo = new ProductExtVo();
		productExtVo.setProId(proId);
		productExtVo.setProSku(proSku);
		List<ProductExtVo> productExtList = new ArrayList<ProductExtVo>();
		productExtList.add(productExtVo);
		
		ProExtSerachVo proExt = new ProExtSerachVo();
		proExt.setMemberId(memberId);
		proExt.setSysId(sysId);
		proExt.setDevice(device);
		proExt.setShowOffShelf(false);
		proExt.setProductExtList(productExtList);
		
		List<ProExtInfoVo> proInfoList = productInfoService.queryProExtInfo(proExt, isLogin);
		if (proInfoList == null || proInfoList.size() < 1) {
			throw new CustomException(ErrorCode.NOT_FIND.getCode(), "商品信息未找到");
		}
		ProExtInfoVo proExtInfoVo = proInfoList.get(0);
		ProRuleSet proRuleSet = null;
		CartProInfo cartProInfo = new CartProInfo();
		
		// 是否积分商品
		if (ProExtInfoVo.IS_YES_1.equals(proExtInfoVo.getIsExchangeIntegral())) {
			cartProInfo.setIsJfProduct(CartProInfo.IS_JF_PRODUCT_YES_1);
			ProductPrice productPrice = productPriceService.findByType(proExtInfoVo.getProId(), sysId, ProductPrice.INTEGRAL);
			// 获取积分价格
			if (productPrice != null && productPrice.getPrice() != null) {
				cartProInfo.setIntegralPrice(productPrice.getPrice().intValue());
			} else {
				cartProInfo.setIntegralPrice(0);
			}
		} else {
			// 非积分商品
			cartProInfo.setIsJfProduct(CartProInfo.IS_JF_PRODUCT_NO_0);
			// 获取非赠品特价商品
			if (!isPremium) {
				proRuleSet = this.canUseSpecialPricePro(memberId, sysId, device, proExtInfoVo.getProSku(), buyNum);
			}
		}
		
		// 优先价格
		if (ProExtInfoVo.IS_YES_1.equals(proExtInfoVo.getIsExchangeIntegral())) {
			// 积分商品的价格=积分单价/50
			cartProInfo.setPriorityPrice(ArithUtil.div(new BigDecimal(cartProInfo.getIntegralPrice()), new BigDecimal(ConstantsUtil.ONE_TO_FIFTH), 2));
		} else if (proExtInfoVo.getIsAgents() != null && proExtInfoVo.getIsAgents() == ProductExtInfo.YES_AGENTS && proExtInfoVo.getMemberPrice() != null) {
			// 代理价
			cartProInfo.setPriorityPrice(proExtInfoVo.getMemberPrice());
		} else if (proRuleSet != null) {
			// 特价
			cartProInfo.setPriorityPrice(proRuleSet.getSpecialPrice());
		} else if (proExtInfoVo.getMemberPrice() != null) {
			// 会员价
			cartProInfo.setPriorityPrice(proExtInfoVo.getMemberPrice());
		} else {
			// 商品价
			cartProInfo.setPriorityPrice(proExtInfoVo.getProPrice());
		}
		
		// 原价
		if (proRuleSet != null) {
			// 特价
			cartProInfo.setFormerPrice(proRuleSet.getSpecialPrice());
			cartProInfo.setRuleSetId(proRuleSet.getRuleSetId());
			cartProInfo.setLimitExplain(proRuleSet.getLimitExplain());
			cartProInfo.setIsStopPrivilege(proRuleSet.getIsStopPrivilege());
		} else {
			// 商品价
			cartProInfo.setFormerPrice(proExtInfoVo.getProPrice());
		}
		
		if (ProductExtInfo.ON_SHELF.equals(proExtInfoVo.getState())) {
			cartProInfo.setIsOnShelves(CartProInfo.IS_ON_SHELVES_YES_1);
		} else {
			cartProInfo.setIsOnShelves(CartProInfo.IS_ON_SHELVES_NO_0);
		}
		
		cartProInfo.setProSku(proExtInfoVo.getProSku());
		cartProInfo.setProPrice(proExtInfoVo.getProPrice());
		cartProInfo.setWeight(proExtInfoVo.getWeight() == null ? new BigDecimal(0.0000) : proExtInfoVo.getWeight());
		cartProInfo.setProName(proExtInfoVo.getProName() == null ? "" : proExtInfoVo.getProName());
		cartProInfo.setImageUrl(proExtInfoVo.getProImg() == null ? "" : proExtInfoVo.getProImg());
		cartProInfo.setBusinessType(proExtInfoVo.getBusinessType());// 自营|联营
		cartProInfo.setBuyUpperLimit(proExtInfoVo.getBuyUpperLimit() == null ? 0 : proExtInfoVo.getBuyUpperLimit());// 最高购买量
		cartProInfo.setBuyLowLimit(proExtInfoVo.getBuyLowLimit() == null ? 0 : proExtInfoVo.getBuyLowLimit());// 最低购买量
		return cartProInfo;
	}
	
	/**
	 * 查询可用特价规则
	 *
	 * @Title: canUseSpecialPricePro 
	 * @author: wuyicheng
	 * @date: 2017年7月24日下午2:24:39 
	 * @param memberId
	 * @param sysId
	 * @param device
	 * @param proSku
	 * @param buyNums
	 * @return
	 * @throws CustomException
	 * @throws
	 */
	@Override
	public ProRuleSet canUseSpecialPricePro(Long memberId, Long sysId, String device, String proSku, BigDecimal buyNums) throws CustomException {
		// 查询可用
		List<RuleSet> ruleSetList = this.getRuleList(sysId, device, Status.ALR_ENABLE.toString(), proSku, RuleType.SPECIAL_PRICE, ShowType.SPECIAL_PRICE, null);
		
		if (ruleSetList == null || ruleSetList.size() <= 0) {
			return null;
		}
		
		// 遍历所有特价规则
		for (RuleSet ruleSet : ruleSetList) {
			CheckRuleSetParam checkRuleSetParam = new CheckRuleSetParam(memberId, sysId, ruleSet, CheckRuleSetParam.USE_1);
			checkRuleSetParam.setCurrentTime(DateUtils.getCurrentDateTime());
			checkRuleSetParam.setBuyNums(buyNums);
			checkRuleSetParam.setDevice(device);
			checkRuleSetParam.setProSku(proSku);
			CheckRuleSetResult checkRuleSetResult = ruleSetService.checkRuleSet(checkRuleSetParam);
			
			// 如果规则满足，返回此规则的特价商品
			if (!(CheckRuleSetResult.YES_1.equals(checkRuleSetResult.getIsCanUse()))) {
				log.info("该特价规则不可用，特价规则ID为:{}，商品SKU:{},会员ID为:{},错误信息：{}", ruleSet.getId(), proSku, memberId, checkRuleSetResult.getErrorCode());
				break;
			}
			ProRuleSet proRuleSet = proRuleSetMapper.findBySkuAndRuleSetId(ruleSet.getId(), proSku);
			// 是否满足停用优惠规则
			proRuleSet.setIsStopPrivilege(ruleSet.getIsStopPrivilege());
			if (RuleSet.YES.equals(ruleSet.getIsStopPrivilege())) {
				proRuleSet.setLimitExplain(ruleSet.getLimitExplain());
			}
			// 只获取第一个特价规则，如果这个特价规则不符合使用条件，就没有特价
			return proRuleSet;
			
		}
		
		return null;
	}
	
	/**
	 * 获取购物车规则
	 *
	 * @Title: getRuleList 
	 * @author: wuyicheng
	 * @date: 2017年7月19日下午1:41:28 
	 * @param sysId 系统ID
	 * @param device 设备
	 * @param status 规则状态
	 * @param proSku 商品SKU
	 * @param ruleType 规则类型
	 * @param showType 促销类型
	 * @param sort
	 * @return
	 * @return: List<RuleSet>
	 * @throws
	 */
	private List<RuleSet> getRuleList(Long sysId, String device, String status, String proSku, RuleType ruleType, ShowType showType, String sort) {
		Map<String, Object> map = new HashMap<>();
		map.put("sysId", sysId);
		map.put("device", device);
		map.put("status", status);
		if (StringUtil.isNotBlank(proSku)) {
			map.put("proSku", proSku);
		}
		if (ruleType != null) {
			map.put("ruleType", ruleType);
		}
		if (showType != null) {
			map.put("showType", showType);
		}
		if (StringUtil.isNotBlank(sort)) {
			map.put("sort", sort);
		}
		return ruleSetMapper.findRuleListByMap(map);
	}
	
	/**
	 * @description : 购物车累加购买数量
	 * @author : wuhaijun
	 * @date : 2017年4月19日 下午3:48:28
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> addBuyNum(CartParam cartParam) throws CustomException {
		Map<String, Object> map = new HashMap<String, Object>();
		CartProInfo cartProInfo = this.getProInfo(cartParam.getProId(), null, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(), BigDecimal.ZERO, false);
		if (CartProInfo.IS_ON_SHELVES_NO_0.equals(cartProInfo.getIsOnShelves())) {
			throw new CustomException(ErrorCode.ON_SHELF.getCode(), "该商品未上架");
		}
		
		cartParam.setActualPayPrice(cartProInfo.getPriorityPrice());
		// 查询该商品是否存在于购物车
		ShoppingCart formerSc = shoppingCartMapper.queryExist(cartParam);
		Integer buyNum = cartParam.getBuyNum() + (formerSc == null ? 0 : formerSc.getBuyNum());
		// 校验最低和最高购买量
		validateBuyNum(buyNum, cartProInfo.getBuyLowLimit(), cartProInfo.getBuyUpperLimit(), cartProInfo.getProName());
		
		if (this.checkStock(cartProInfo.getProSku(), new BigDecimal(buyNum)) == false) {
			// 获取商品库存Map集
			Map<String, Map<String, Object>> products = productInfoService.getStock(cartProInfo.getProSku());
			// 获取Sku对应的有效库存Map
			Map<String, Object> validstocks = products.get(cartProInfo.getProSku());
			BigDecimal stockNum = (BigDecimal) validstocks.get("validStock");
			int validStock = 0;
			if (null != stockNum) {
				validStock = stockNum.intValue();
			}
			if (validStock <= 0) {
				// 库存数量为0 库存设置为1
				cartParam.setBuyNum(1);
			} else if (validStock > 0 && validStock < buyNum) {
				// 库存数量小于最大购买数量 购物车数量设置为库存最大数量
				cartParam.setBuyNum(validStock);
			}
			shoppingCartMapper.updateBuyNum(cartParam);
			throw new CustomException(ErrorCode.STORAGE_INSUFFICIENT.getCode(), "该商品库存不足");
			
		}
		
		cartParam.setIsPremium(ShoppingCart.PREMIUM_NO);
		if (formerSc == null) {// 新增
			shoppingCartMapper.newAdd(cartParam);
		} else {// 累加
			shoppingCartMapper.upAdd(cartParam);
		}
		
		return map;
	}
	
	/**
	 * @description : 购物车更新购买数量
	 * @author : wuhaijun
	 * @date : 2017年4月19日 下午5:42:33
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> updateBuyNum(CartParam cartParam) throws CustomException {
		Map<String, Object> map = new HashMap<String, Object>();
		CartProInfo cartProInfo = this.getProInfo(cartParam.getProId(), null, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(),
				new BigDecimal(cartParam.getBuyNum()), false);
		
		if ("0".equals(cartProInfo.getIsOnShelves())) {
			throw new CustomException(ErrorCode.ON_SHELF.getCode(), "该商品未上架");
		}
		// 查询库存
		Map<String, Map<String, Object>> returnMap = this.findCisBranchStockByProSkus(cartProInfo.getProSku());
		// 校验库存
		boolean isFull = this.checkStock(cartProInfo.getProSku(), new BigDecimal(cartParam.getBuyNum()), returnMap);
		// 获取最大库存量
		Map<String, Object> proStockMap = returnMap.get(cartProInfo.getProSku());
		Integer validStock = new BigDecimal(proStockMap.get("validStock").toString()).intValue();
		if (validStock < 1) {
			log.info("购买商品SKU【" + cartProInfo.getProSku() + "】的库存量小于1.0000");
			throw new CustomException(ErrorCode.STORAGE_INSUFFICIENT.getCode(), "该商品库存不足");
		}
		boolean isChange = false;
		if (isFull == false) {
			// 2.先判断库存量，当数量栏位>=库存量，再去判断是否设定最低起购量，
			// a.若无设定，则取库存量；
			// b.若设定，则比较库存量&最低起购量， 库存量>=最低起购量，则数量= 库存量；库存量<最低起购量，则数量=最低起购量；
			if (cartProInfo.getBuyLowLimit() != null && cartProInfo.getBuyLowLimit() > 0 && validStock < cartProInfo.getBuyLowLimit()) {
				cartParam.setBuyNum(cartProInfo.getBuyLowLimit());
				map.put("buyNum", cartProInfo.getBuyLowLimit());
				isChange = true;
			}
			// 当数量栏位>=库存量，再去判断最高起购量，
			// a.若无设定，则取库存量；
			// b.若设定，则比较库存量&最高起购量，库存量>=最高起批量，则数量=最高起批量；库存量<最高起批量，则数量=库存量；
			if (cartProInfo.getBuyUpperLimit() != null && cartProInfo.getBuyUpperLimit() > 0 && validStock > cartProInfo.getBuyUpperLimit()) {
				cartParam.setBuyNum(cartProInfo.getBuyUpperLimit());
				map.put("buyNum", cartProInfo.getBuyUpperLimit());
				isChange = true;
			}
			
			if (!isChange) {
				cartParam.setBuyNum(validStock);
				map.put("buyNum", validStock);
				log.info("购买商品SKU【" + cartProInfo.getProSku() + "】的库存量已上限");
			}
		} else {
			// 3.当数量栏位<库存量，再去判断是 否设定最低起购量；
			// a.若无设定，则取数量；
			// b.若有设定，则比较数量&最低起购量，数量>=最低起购量，则数量本身不变； 数量<=最低起购量，则数量=最低起购量；
			if (cartProInfo.getBuyLowLimit() != null && cartProInfo.getBuyLowLimit() > 0 && cartParam.getBuyNum() < cartProInfo.getBuyLowLimit()) {
				cartParam.setBuyNum(cartProInfo.getBuyLowLimit());
				map.put("buyNum", cartProInfo.getBuyLowLimit());
			}
			// 当数量栏位<库存量，再去判断是否设定最高起批量；
			// a.若无设定，则取数量；
			// b.若有设定，则比较数量&最高起批量，数量>=最高起批量,则数量=最高起量； 数量<最高起批量，则数量本身不变；
			if (cartProInfo.getBuyUpperLimit() != null && cartProInfo.getBuyUpperLimit() > 0 && cartParam.getBuyNum() > cartProInfo.getBuyUpperLimit()) {
				cartParam.setBuyNum(cartProInfo.getBuyUpperLimit());
				map.put("buyNum", cartProInfo.getBuyUpperLimit());
			}
		}
		
		map.put("isDisable", false);
		// 4.当最低起购量>库存量，或最高起购量<最低购量，则在购物车中显示为失效商品
		if (cartProInfo.getBuyLowLimit() != null && cartProInfo.getBuyLowLimit() > 0 && cartProInfo.getBuyLowLimit() > validStock) {
			map.put("isDisable", true);
		}
		if (cartProInfo.getBuyLowLimit() != null && cartProInfo.getBuyLowLimit() > 0 && cartProInfo.getBuyUpperLimit() != null && cartProInfo.getBuyUpperLimit() > 0
				&& cartProInfo.getBuyLowLimit() > cartProInfo.getBuyUpperLimit()) {
			map.put("isDisable", true);
		}
		cartParam.setActualPayPrice(cartProInfo.getPriorityPrice());
		shoppingCartMapper.updateBuyNum(cartParam);
		map.put("buyLowLimit", cartProInfo.getBuyLowLimit());// 下限
		map.put("buyUpperLimit", cartProInfo.getBuyUpperLimit());// 上限
		return map;
	}
	
	/**
	 * 校验购买数量
	  *  @Title: validateBuuNum
	  * @author joy.zhang
	  * @date 2017年8月9日 下午3:49:42
	  * @param buyNum
	  * @param buyLowLimit
	  * @param buyUpperLimit
	  * @throws CustomException
	  * @return void
	 */
	public void validateBuyNum(Integer buyNum, Integer buyLowLimit, Integer buyUpperLimit, String proName) throws CustomException {
		if (buyLowLimit == null) {
			buyLowLimit = 0;
		}
		if (buyUpperLimit == null) {
			buyUpperLimit = 0;
		}
		if (proName == null) {
			proName = "";
		}
		if (buyLowLimit > 0 && buyNum < buyLowLimit) {
			throw new CustomException(ErrorCode.BUY_LOWER_OUT.getCode(), proName + ErrorCode.BUY_LOWER_OUT.getCnMessage());
		}
		if (buyUpperLimit > 0 && buyNum > buyUpperLimit) {
			throw new CustomException(ErrorCode.BUY_UPPER_OUT.getCode(), proName + ErrorCode.BUY_UPPER_OUT.getCnMessage());
		}
	}
	
	/**
	 * @description : 删除购物车
	 * @author : wuhaijun
	 * @date : 2017年4月19日 下午7:11:59
	 */
	@Override
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> del(String ids) {
		Map<String, Object> map = new HashMap<String, Object>();
		shoppingCartMapper.del(ids.split(","));
		return map;
	}
	
	/**
	 * @description : 购物车查询
	 * @author : wuhaijun
	 * @date : 2017年4月19日 下午6:38:56
	 */
	@Override
	public Map<String, Object> query(CartParam cartParam) throws CustomException {
		Map<String, Object> map = new HashMap<String, Object>();
		
		MemberAccount memberAccount = memberAccountService.findByMemberIdAndSysId(cartParam.getBuyerId(), cartParam.getSysId());
		if (memberAccount == null) {
			throw new CustomException(ErrorCode.MEMBER_ACCOUNT_NOT_EXIST);
		}
		
		// 判断会员是否禁用
		if (memberAccountService.filterMemberStatus(memberAccount, null)) {
			throw new CustomException(ErrorCode.MEMBER_IS_FREEZE);
		}
		
		List<ShoppingCart> cartList = shoppingCartMapper.query(cartParam.getBuyerId(), cartParam.getSysId());
		if (cartList == null || cartList.size() < 1) {
			throw new CustomException(ErrorCode.NO_COMMODITY.getCode(), "购物车没有商品");
		}
		MemberLevel memberLevel = memberLevelService.findByMemberIdAndSysId(cartParam.getBuyerId(), cartParam.getSysId());
		if ("V13".equals(memberLevel.getLever())) {
			cartParam.setIsAgent(true);
		}
		Map<String, Map<String, Object>> returnMap = getSkuStockMap(cartList);
		// 商品总额
		BigDecimal proTotalAmount = new BigDecimal(0.00);
		// 失效商品，指的是商品未上架
		List<ShoppingCart> disableList = new ArrayList<ShoppingCart>();
		// 总的购买数量
		int totalBuyNum = 0;
		int cartLen = cartList.size();
		for (int i = 0; i < cartLen; i++) {
			ShoppingCart cart = cartList.get(i);
			
			CartProInfo cartProInfo = this.getProInfo(cart.getProId(), null, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(), new BigDecimal(cart.getBuyNum()),
					(ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) ? true : false);
			
			cart.setImageUrl(cartProInfo.getImageUrl());
			cart.setProName(cartProInfo.getProName());
			cart.setProSku(cartProInfo.getProSku());
			cart.setActualPayPrice(cartProInfo.getPriorityPrice());
			cart.setFormerPrice(cartProInfo.getFormerPrice());
			cart.setBusinessType(cartProInfo.getBusinessType());
			cart.setPriorityPrice(cartProInfo.getPriorityPrice());
			cart.setWeight(cartProInfo.getWeight());
			BigDecimal actualPaySubtotal = new BigDecimal(0.00);// 实付小计
			BigDecimal subtotal = new BigDecimal(0.00);// 小计
			//// 判断是否是积分商品
			if (CartProInfo.IS_JF_PRODUCT_YES_1.equals(cartProInfo.getIsJfProduct())) {
				
				cart.setIsIntegralPro(ShoppingCart.INTEGRAL_PRO_YES_1);
				cart.setActualPayIntegral(BigDecimal.ZERO);
				cart.setActualPayIntegralSum(0);
				cart.setIntegralPrice(cartProInfo.getIntegralPrice());
				cart.setIntegralSubtotal(cartProInfo.getIntegralPrice() * cart.getBuyNum());
			} else {
				// 非积分商品
				cart.setIsIntegralPro(ShoppingCart.INTEGRAL_PRO_NO_0);
				cart.setActualPayIntegral(BigDecimal.ZERO);
				cart.setActualPayIntegralSum(0);
				cart.setIntegralPrice(0);
				cart.setIntegralSubtotal(0);
				
				// 实付小计(实付价 * 数量)
				actualPaySubtotal = ArithUtil.mul(cart.getActualPayPrice(), new BigDecimal(cart.getBuyNum()), 2);
				cart.setActualPaySubtotal(actualPaySubtotal);
				// 判断是否是赠品
				if (!ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) {
					subtotal = ArithUtil.mul(cartProInfo.getPriorityPrice(), new BigDecimal(cart.getBuyNum()), 2);
				}
				cart.setSubtotal(subtotal);
			}
			cart.setSubtotal(subtotal);
			
			// 对商品进行校验
			if (validateProduct(cart, cartProInfo, returnMap) > 1) {
				disableList.add(cart);
				cartList.remove(i);
				cartLen--;
				i--;
				continue;
			}
			
			cartParam.setUseTotalIntegral(cartParam.getUseTotalIntegral() + cart.getActualPayIntegralSum());
			cartParam.setTotalIntegral(cartParam.getTotalIntegral() + cart.getIntegralSubtotal());
			totalBuyNum = totalBuyNum + cart.getBuyNum();
			proTotalAmount = ArithUtil.add(proTotalAmount, subtotal, 2);
		}
		map.put("cartList", cartList);
		map.put("proTotalNum", cartList.size());// 商品总数量
		map.put("totalBuyNum", totalBuyNum);// 购买商品总数量
		map.put("totalIntegral", cartParam.getTotalIntegral());// 积分商品总计
		map.put("proTotalAmount", proTotalAmount);// 商品折前总额
		map.put("disableList", disableList);
		
		// 匹配购物车规则
		this.shoppingCartRuleSet(cartParam, cartList, map);
		
		// 将赠送商品放入礼品列表
		this.addGiftAndRemoveShoppingCart(cartParam, cartList);
		
		// 赠品
		map.put("giftList", cartParam.getGiftList());
		
		return map;
	}
	
	/**
	 * @description : 获取满足购物车规则的赠品
	 * @author : wuhaijun
	 * @param giveSum 
	 * @date : 2017年4月27日 上午8:55:29
	 */
	private void getGiftList(List<ShoppingCart> shoppingCartList, Map<String, BigDecimal> limitProMap, CartParam cartParam, RuleSet ruleSet, BigDecimal giveSum)
			throws CustomException {
		
		// 没有符合赠送商品规则的商品
		if (limitProMap == null || limitProMap.size() <= 0) {
			return;
		}
		// 获取赠品列表
		List<Gift> giftList = cartParam.getGiftList();
		if (giftList == null || giftList.size() <= 0) {
			giftList = new ArrayList<>();
		}
		
		String[] giveProSkus = ruleSet.getGiveCode().split(ConstantsUtil.COMMA);
		for (String giveProSku : giveProSkus) {
			CartProInfo cartProInfo = this.getProInfo(null, giveProSku, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(), BigDecimal.ZERO, true);
			// 如果赠品已失效,则continue
			if (CartProInfo.IS_ON_SHELVES_NO_0.equals(cartProInfo.getIsOnShelves())) {
				continue;
			}
			Gift gift = new Gift();
			gift.setRuleName(ruleSet.getShowName());
			gift.setImageUrl(cartProInfo.getImageUrl());
			gift.setProName(cartProInfo.getProName());
			gift.setProSku(cartProInfo.getProSku());
			gift.setActualPayPrice(new BigDecimal(0.00));
			if (CartProInfo.IS_JF_PRODUCT_YES_1.equals(cartProInfo.getIsJfProduct())) {
				// 积分商品，价格取积分转换后的价格
				gift.setProPrice(cartProInfo.getPriorityPrice());
			} else {
				gift.setProPrice(cartProInfo.getProPrice());
			}
			gift.setGiftNum(giveSum.intValue());
			gift.setFormerPrice(cartProInfo.getFormerPrice());
			gift.setSubtotal(new BigDecimal(0.00));
			gift.setWeight(cartProInfo.getWeight());
			gift.setBusinessType(cartProInfo.getBusinessType());
			gift.setRuleSetId(ruleSet.getId());
			gift.setRuleName(ruleSet.getShowName());
			gift.setCartId(null);
			gift.setIsIntegralPro(cartProInfo.getIsJfProduct());
			gift.setIntegralPrice(0);
			giftList.add(gift);
			// 把赠品的重量加进去
			BigDecimal subWeight = ArithUtil.mul(cartProInfo.getWeight(), new BigDecimal(gift.getGiftNum()), 4);
			BigDecimal totalWeight = ArithUtil.add(cartParam.getTotalWeight(), subWeight, 4);
			cartParam.setTotalWeight(totalWeight);
		}
		
		cartParam.setGiftList(giftList);
	}
	
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> settleView(CartParam cartParam, List<ShoppingCart> shoppingCartList) throws CustomException, ParseException {
		
		Map<String, Object> map = new HashMap<String, Object>();
		
		if (shoppingCartList != null && shoppingCartList.size() > 0) {
			// 获得商品库存
			Map<String, Map<String, Object>> returnMap = getSkuStockMap(shoppingCartList);
			// 对商品进行校验
			for (ShoppingCart cart : shoppingCartList) {
				CartProInfo cartProInfo = this.getProInfo(cart.getProId(), null, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(),
						new BigDecimal(cart.getBuyNum()), (ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) ? true : false);
				if (validateProduct(cart, cartProInfo, returnMap) > 0) {
					throw new CustomException(ErrorCode.SHOPPING_CART_CANNOT_SUBMIT.getCode(), ErrorCode.SHOPPING_CART_CANNOT_SUBMIT.getCnMessage());
				}
			}
		}
		
		// 收货地址
		DeliveryAddress addr = new DeliveryAddress();
		addr.setMemberId(cartParam.getBuyerId());
		addr.setSysId(cartParam.getSysId());
		List<DeliveryAddress> receiveAddrList = deliveryAddressService.findListByMemberIdAndSysId(addr, null);
		map.put("receiveAddrList", receiveAddrList);
		
		// 支付方式
		List<Map<String, Object>> payMethodList = shoppingCartMapper.queryPayMethod(null);
		map.put("payMethodList", payMethodList);
		
		// 配送方式
		List<Map<String, Object>> deliveryMethodList = shoppingCartMapper.queryDeliveryMethod(null);
		map.put("deliveryMethodList", deliveryMethodList);
		
		// 默认收货地址省编码
		if (receiveAddrList != null && receiveAddrList.size() > 0) {
			for (DeliveryAddress da : receiveAddrList) {
				if (da.getIsDefault() != null && da.getIsDefault() == 1) {
					cartParam.setProvinceCode(da.getProvinceCode());
					cartParam.setReceiveAddrId(da.getId());
					break;
				}
			}
		}
		
		// 默认支付编码
		for (Map<String, Object> payMap : payMethodList) {
			if (ConstantsUtil.PAYMETHOD_DEFAULT_1.equals(payMap.get("isDefault").toString())) {
				cartParam.setPayMethodCode(payMap.get("code").toString());
				break;
			}
			
		}
		
		// 默认快递编码
		for (Map<String, Object> deliveryMap : deliveryMethodList) {
			if (ConstantsUtil.DELIVERY_METHOD_DEFAULT_1.equals(deliveryMap.get("isDefault").toString())) {
				cartParam.setDeliveryMethodCode(deliveryMap.get("code").toString());
				break;
			}
		}
		
		// 默认不使用积分
		cartParam.setIsUseIntegral(CartParam.IS_USE_INTEGRAL_YES_1);
		
		this.calculateShoppingCart(cartParam, map, shoppingCartList);
		
		return map;
	}
	
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> settle(CartParam cartParam, List<ShoppingCart> shoppingCartList) throws CustomException, ParseException {
		Map<String, Object> map = new HashMap<String, Object>();
		this.calculateShoppingCart(cartParam, map, shoppingCartList);
		return map;
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(rollbackFor = { Exception.class })
	public Map<String, Object> submitOrder(CartParam cartParam, List<ShoppingCart> shoppingCartList) throws CustomException, ParseException {
		
		Map<String, Object> map = new HashMap<String, Object>();
		
		this.calculateShoppingCart(cartParam, map, shoppingCartList);
		
		String cartSkus = cartParam.getCartSkus();
		DeliveryAddress deliveryAddress = cartParam.getDeliveryAddress();
		List<ShoppingCart> cartList = (List<ShoppingCart>) map.get("cartList");
		
		// 检验库存
		Map<String, Map<String, Object>> returnMap = this.findCisBranchStockByProSkus(cartSkus);
		for (ShoppingCart cart : cartList) {
			// 校验商品购买上下限
			CartProInfo cartProInfo = this.getProInfo(cart.getProId(), null, cart.getSysId(), cart.getBuyerId(), cartParam.getDevice(), new BigDecimal(cart.getBuyNum()), false);
			validateBuyNum(cart.getBuyNum(), cartProInfo.getBuyLowLimit(), cartProInfo.getBuyUpperLimit(), cartProInfo.getProName());
			
			// 校验商品库存
			if (!this.checkStock(cart.getProSku(), new BigDecimal(cart.getBuyNum()), returnMap)) {
				throw new CustomException(ErrorCode.STORAGE_INSUFFICIENT.getCode(), "商品库存不足");
			}
			
		}
		
		PayOrderVo payOrderVo = new PayOrderVo();
		
		if (map.get("useRuleSetList") != null) {
			// 使用规则列表
			List<UseRuleSetVo> useRuleSetList = (List<UseRuleSetVo>) map.get("useRuleSetList");
			
			try {
				this.buildUseLogAndGivingInfo(cartParam, useRuleSetList, payOrderVo);
			} catch (IllegalAccessException e) {
				log.info(e.getMessage());
			} catch (InvocationTargetException e) {
				log.info(e.getMessage());
			} catch (NoSuchMethodException e) {
				log.info(e.getMessage());
			}
		}
		
		List<OrderDetailVo> orderDetails = new ArrayList<OrderDetailVo>();
		// 正常商品
		for (ShoppingCart cart : cartList) {
			OrderDetailVo orderDetailVo = new OrderDetailVo();
			orderDetailVo.setBusinessType(BusinessType.SELF_SALES.toString());
			orderDetailVo.setGiveCashBackSum(new BigDecimal(0.00));
			orderDetailVo.setPackNo(null);
			orderDetailVo.setPackWeight(null);
			orderDetailVo.setPremiums(PremiumEnum.NO_PREMIUM.toString());
			orderDetailVo.setProductName(cart.getProName());
			orderDetailVo.setProSku(cart.getProSku());
			orderDetailVo.setProductNum(new BigDecimal(cart.getBuyNum()));
			orderDetailVo.setProductPrice(cart.getPriorityPrice());
			orderDetailVo.setProductProperty(null);
			orderDetailVo.setPurchasePrice(cart.getActualPayPrice());
			orderDetailVo.setSubtotal(cart.getSubtotal());
			orderDetailVo.setActualPaySubtotal(cart.getActualPaySubtotal());
			orderDetailVo.setUseRuleSum(cart.getUseRuleSum());
			orderDetailVo.setSupplierId(null);
			orderDetailVo.setUseCashBackSum(new BigDecimal(0.00));
			orderDetailVo.setGiveJfSum(cart.getGiveIintegral());
			orderDetailVo.setJfPrice(cart.getIntegralPrice());
			orderDetailVo.setJfSubtotal(new BigDecimal(cart.getIntegralSubtotal()));
			orderDetailVo.setJfPurchasePrice(cart.getActualPayIntegral());
			orderDetailVo.setUseJfSum(cart.getActualPayIntegralSum());
			orderDetailVo.setIsJfProduct(cart.getIsIntegralPro());
			orderDetailVo.setUseRedPacketSum(cart.getUseRedPacketAmount());
			orderDetails.add(orderDetailVo);
		}
		// 赠品
		List<Gift> giftList = cartParam.getGiftList();// 去重复
		if (giftList != null && giftList.size() > 0) {
			for (Gift gift : giftList) {
				OrderDetailVo orderDetailVo = new OrderDetailVo();
				orderDetailVo.setBusinessType(BusinessType.SELF_SALES.toString());
				orderDetailVo.setGiveCashBackSum(new BigDecimal(0.00));
				orderDetailVo.setPackNo(null);
				orderDetailVo.setPackWeight(null);
				
				// 是否是购物车里的赠品
				if (gift.getCartId() != null) {
					orderDetailVo.setPremiums(PremiumEnum.GIVE_ADD_PREMIUM.toString());
				} else {
					orderDetailVo.setPremiums(PremiumEnum.CART_PREMIUM.toString());
				}
				orderDetailVo.setProductName(gift.getProName());
				orderDetailVo.setProSku(gift.getProSku());
				orderDetailVo.setProductNum(new BigDecimal(gift.getGiftNum()));
				orderDetailVo.setProductPrice(gift.getProPrice());
				orderDetailVo.setProductProperty(null);
				orderDetailVo.setPurchasePrice(new BigDecimal(0.00));
				orderDetailVo.setSubtotal(new BigDecimal(0.00));
				orderDetailVo.setSupplierId(null);
				orderDetailVo.setUseCashBackSum(new BigDecimal(0.00));
				orderDetailVo.setUseRedPacketSum(new BigDecimal(0.00));
				orderDetailVo.setRuleSetId(gift.getRuleSetId());
				orderDetailVo.setRuleName(gift.getRuleName());
				orderDetailVo.setGiveJfSum(0);
				orderDetailVo.setIsJfProduct(gift.getIsIntegralPro());
				orderDetailVo.setJfPurchasePrice(new BigDecimal(0));
				orderDetailVo.setUseJfSum(0);
				orderDetailVo.setJfPrice(gift.getIntegralPrice());
				orderDetailVo.setJfSubtotal(new BigDecimal(0));
				orderDetails.add(orderDetailVo);
			}
		}
		payOrderVo.setAddress(deliveryAddress.getProvinceName() + deliveryAddress.getCityName() + deliveryAddress.getAreaName() + deliveryAddress.getDetailAddress());
		payOrderVo.setCityCode(deliveryAddress.getCityCode());
		payOrderVo.setCountyCode(deliveryAddress.getAreaCode());
		payOrderVo.setCreateMemberId(cartParam.getBuyerId());
		
		Map<String, Object> expressMap = shoppingCartMapper.queryExpressByOne(null, cartParam.getDeliveryMethodCode(), null);
		payOrderVo.setExpressDeliveryName(expressMap.get("dataName").toString());
		payOrderVo.setExpressDeliveryCode(cartParam.getDeliveryMethodCode());
		payOrderVo.setFreightSum(cartParam.getFreight());
		payOrderVo.setGiveCashBackSum(new BigDecimal(0.00));
		
		/*****发票修改（增加判断必填项是否为空）*****/
		// 发票信息
		if (InvoiceType.ELECTRONIC_INVOICE.toString().equals(cartParam.getInvoiceCode()) && cartParam.getDevice().equals("PC")) {
			// 电子发票(PC端)
			if (StringUtil.isBlank(cartParam.getInvoiceTitle()) || (InvoiceType.COMPANY.toString().equals(cartParam.getInvoiceTitle())
					&& (StringUtil.isBlank(cartParam.getCompanyName()) || StringUtil.isBlank(cartParam.getTaxpayersNo()) || StringUtil.isBlank(cartParam.getEmail())))) {
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				StringBuffer msg = new StringBuffer("未填写：");
				if (StringUtil.isBlank(cartParam.getEmail())) {
					msg.append("[电子邮箱]");
				}
				if (StringUtil.isBlank(cartParam.getCompanyName())) {
					msg.append("[公司名称]");
				}
				if (StringUtil.isBlank(cartParam.getTaxpayersNo())) {
					msg.append("[纳税人识别号]");
				}
				c.setMessage(msg.toString());
				throw c;
			}
			if (StringUtil.isBlank(cartParam.getInvoiceTitle())
					|| (InvoiceType.PERSONAL.toString().equals(cartParam.getInvoiceTitle()) && StringUtil.isBlank(cartParam.getEmail()))) {
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				c.setMessage("未填写：[电子邮箱]");
				throw c;
			}
		} else if (InvoiceType.ELECTRONIC_INVOICE.toString().equals(cartParam.getInvoiceCode()) && cartParam.getDevice().equals("WAP")) {
			// 电子发票(WAP端)
			if (StringUtil.isBlank(cartParam.getInvoiceTitle()) || (InvoiceType.COMPANY.toString().equals(cartParam.getInvoiceTitle())
					&& (StringUtil.isBlank(cartParam.getCompanyName()) || StringUtil.isBlank(cartParam.getTaxpayersNo())))) {
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				StringBuffer msg = new StringBuffer("未填写：");
				if (StringUtil.isBlank(cartParam.getCompanyName())) {
					msg.append("[公司名称]");
				}
				if (StringUtil.isBlank(cartParam.getTaxpayersNo())) {
					msg.append("[纳税人识别号]");
				}
				c.setMessage(msg.toString());
				throw c;
			}
			if (StringUtil.isBlank(cartParam.getInvoiceTitle())
					|| (InvoiceType.PERSONAL.toString().equals(cartParam.getInvoiceTitle()) && StringUtil.isBlank(cartParam.getEmail()))) {
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				c.setMessage("未填写：[电子邮箱]");
				throw c;
			}
			
		} else if (InvoiceType.ORDINARY_INVOICE.toString().equals(cartParam.getInvoiceCode())) {
			// 普通发票(PC端+WAP)
			if (StringUtil.isBlank(cartParam.getInvoiceTitle()) || (InvoiceType.COMPANY.toString().equals(cartParam.getInvoiceTitle())
					&& (StringUtil.isBlank(cartParam.getTaxpayersNo()) || StringUtil.isBlank(cartParam.getCompanyName())))) {
				
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				
				StringBuffer msg = new StringBuffer("未填写：");
				if (StringUtil.isBlank(cartParam.getCompanyName())) {
					msg.append("[公司名称]");
				}
				if (StringUtil.isBlank(cartParam.getTaxpayersNo())) {
					msg.append("[纳税人识别号]");
				}
				c.setMessage(msg.toString());
				throw c;
			}
			
		} else if (InvoiceType.VTA_INVOICE.toString().equals(cartParam.getInvoiceCode())) {
			// 增值税务发票(PC+WAP)
			if (StringUtil.isBlank(cartParam.getCompanyName()) || StringUtil.isBlank(cartParam.getTaxpayersNo()) || StringUtil.isBlank(cartParam.getRegisterAddress())
					|| StringUtil.isBlank(cartParam.getRegisterMobilePhone()) || StringUtil.isBlank(cartParam.getOpenBank()) || StringUtil.isBlank(cartParam.getOpenAccount())) {
				CustomException c = new CustomException(ErrorCode.ORDER_INVOICE_INCOMPLETE);
				
				StringBuffer msg = new StringBuffer("未填写：");
				if (StringUtil.isBlank(cartParam.getCompanyName())) {
					msg.append("[公司名称]");
				}
				if (StringUtil.isBlank(cartParam.getTaxpayersNo())) {
					msg.append("[纳税人识别号]");
				}
				if (StringUtil.isBlank(cartParam.getRegisterAddress())) {
					msg.append("[注册地址]");
				}
				if (StringUtil.isBlank(cartParam.getRegisterMobilePhone())) {
					msg.append("[注册手机]");
				}
				if (StringUtil.isBlank(cartParam.getOpenBank())) {
					msg.append("[开户银行]");
				}
				if (StringUtil.isBlank(cartParam.getOpenAccount())) {
					msg.append("[开户账号]");
				}
				c.setMessage(msg.toString());
				throw c;
				
			}
		}
		
		payOrderVo.setInvoiceContent(cartParam.getInvoiceContent());
		payOrderVo.setInvoiceTitle(cartParam.getInvoiceTitle());
		payOrderVo.setInvoiceType(cartParam.getInvoiceCode());
		payOrderVo.setCompanyName(cartParam.getCompanyName());
		payOrderVo.setRegisterAddress(cartParam.getRegisterAddress());
		payOrderVo.setRegisterMobilePhone(cartParam.getRegisterMobilePhone());
		payOrderVo.setTaxpayersNo(cartParam.getTaxpayersNo());
		payOrderVo.setOpenAccount(cartParam.getOpenAccount());
		payOrderVo.setOpenBank(cartParam.getOpenBank());
		payOrderVo.setEmail(cartParam.getEmail());
		/*****发票修改↑*****/
		
		payOrderVo.setIsBrushOrder((short) 0);
		payOrderVo.setPayType(cartParam.getPayMethodCode());
		payOrderVo.setOrderRemark(cartParam.getOrderRemark());
		payOrderVo.setCustomerRemark(cartParam.getCustomerRemark());
		payOrderVo.setTelephone(deliveryAddress.getPhone());// 电话
		payOrderVo.setPhone(deliveryAddress.getMobilePhone());// 手机
		payOrderVo.setProvinceCode(deliveryAddress.getProvinceCode());
		payOrderVo.setReceiptName(deliveryAddress.getRecName());
		payOrderVo.setSysId(cartParam.getSysId());
		payOrderVo.setStreetAddress(deliveryAddress.getDetailAddress());
		payOrderVo.setTotalWeight(cartParam.getTotalWeight());
		payOrderVo.setUseCashBackSum(new BigDecimal(0.00));
		payOrderVo.setUseRebateSum(new BigDecimal(0.00));
		payOrderVo.setUseRedPacketId(cartParam.getUseRedPacketId());
		payOrderVo.setUseRedPacketSum(cartParam.getRedPacketDeduction());
		
		payOrderVo.setDevice(cartParam.getDevice());
		payOrderVo.setProductPaySum(cartParam.getProTotalAmount());
		payOrderVo.setRedPacketName(cartParam.getUseRedPacketName());
		payOrderVo.setOrderDetails(orderDetails);
		payOrderVo.setCreateId(cartParam.getCreateId());
		payOrderVo.setIsFromBack(cartParam.getIsFromBack());
		payOrderVo.setGrowthValue(cartParam.getGrowthValue());
		payOrderVo.setUseRuleDiscountSum(cartParam.getUseRuleDiscountSum());
		payOrderVo.setUseJfSum(cartParam.getUseTotalIntegral());
		payOrderVo.setProductJfSum(cartParam.getTotalIntegral());
		payOrderVo.setGiveJfSum(cartParam.getGiveTotalIntegral());
		MemberAccount memberAccount = memberAccountService.findByMemberIdAndSysId(cartParam.getBuyerId(), cartParam.getSysId());
		// 会员不存在
		if (memberAccount == null) {
			throw new CustomException(ErrorCode.MEMBER_ACCOUNT_NOT_EXIST.getCode(), "会员账号信息不存在");
		}
		
		// 7. 使用充值余额抵扣
		BigDecimal actualPayTotalAmount = cartParam.getActualPayTotalAmount();// 订单应付总价
		BigDecimal useStoreBalance = new BigDecimal(0.00);// 使用充值余额
		/*BigDecimal totalAmount = memberAccount.getTotalAmount();// 账户充值余额
		// i. 充值余额最后做抵扣。如果全部抵扣，则支付金额为0，订单提示支付成功。这部分金额不分摊。
		if (CartParam.IS_USE_YES_1.equals(cartParam.getUseStoreBalance())) {
			if (ArithUtil.compareTo(actualPayTotalAmount, totalAmount) >= 0) {
				useStoreBalance = totalAmount;
				actualPayTotalAmount = ArithUtil.sub(actualPayTotalAmount, useStoreBalance, 2);
			} else {
				useStoreBalance = actualPayTotalAmount;
				totalAmount = ArithUtil.sub(totalAmount, useStoreBalance, 2);
				actualPayTotalAmount = new BigDecimal(0.00);
			}
			
		}*/
		payOrderVo.setUseStoreValue(useStoreBalance);
		payOrderVo.setOrderSum(actualPayTotalAmount);
		Result<Map<String, Object>> result = payOrderService.submitPayOrder(payOrderVo);
		// 提交订单删除相对应的购物车
		if (cartParam.getCartIds() != null) {
			shoppingCartMapper.delCartBySubmitOrder(cartParam.getCartIds().split(","), cartParam.getBuyerId(), cartParam.getSysId());
		}
		map = result.getData();
		
		return map;
	}
	
	/**
	 * 构建使用记录和赠送记录信息
	 *
	 * @Title: buildUseLogAndGivingInfo 
	 * @author: wuyicheng
	 * @date: 2017年7月20日上午10:00:20 
	 * @param cartParam
	 * @param useRuleSetList
	 * @param payOrderVo
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 * @return: void
	 * @throws
	 */
	private void buildUseLogAndGivingInfo(CartParam cartParam, List<UseRuleSetVo> useRuleSetList, PayOrderVo payOrderVo)
			throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		List<RuleSetUseLog> ruleSetUseLogs = new ArrayList<>(); // 规则使用记录
		
		for (UseRuleSetVo useRuleSetVo : useRuleSetList) {
			// 使用记录
			RuleSetUseLog ruleSetUseLog = new RuleSetUseLog();
			
			PropertyUtils.copyProperties(ruleSetUseLog, useRuleSetVo);
			ruleSetUseLog.setMemberId(cartParam.getBuyerId());
			ruleSetUseLog.setSysId(cartParam.getSysId());
			// 减金额 免邮费 送商品
			if (useRuleSetVo.getShowType() == null || ShowType.SUB_AMOUNT.toString().equals(useRuleSetVo.getShowType())
					|| ShowType.FREE_POSTAGE.toString().equals(useRuleSetVo.getShowType()) || ShowType.GIVE_PRO.toString().equals(useRuleSetVo.getShowType())
					|| ShowType.SPECIAL_PRICE.toString().equals(useRuleSetVo.getShowType())) {
				ruleSetUseLog.setIsGiving(RuleSetUseLog.IS_GIVING_YES_1);
			} else {
				ruleSetUseLog.setIsGiving(RuleSetUseLog.IS_GIVING_NO_0);
			}
			ruleSetUseLogs.add(ruleSetUseLog);
		}
		payOrderVo.setRuleSetUseLogs(ruleSetUseLogs);
	}
	
	/**
	 * @description : 计算均摊
	 * @author : wuhaijun
	 * @date : 2017年5月4日 下午2:05:07
	 */
	private void computeShare(List<ShoppingCart> cartList, CartParam cartParam) {
		// 单件商品所使用的优惠金额=(商品小计/商品总计)*优惠金额/购买数量
		// 优惠后的支付价格=支付价格-单件商品所使用的优惠金额
		
		// 商品折前总额
		BigDecimal proTotalAmount = cartParam.getProTotalAmount();
		// 商品折后总额
		BigDecimal dedProTotalAmount = cartParam.getDedProTotalAmount();
		// 优惠金额(优惠针对于整个购物车)
		BigDecimal discountAmount = cartParam.getDiscountAmount();
		// 红包抵扣
		BigDecimal redPacketDeduction = cartParam.getRedPacketDeduction();
		// 红包金额大于0
		if (ArithUtil.compareTo(redPacketDeduction, new BigDecimal(0.00)) <= 0) {
			return;
		}
		// 均摊支付价格
		if (ArithUtil.compareTo(redPacketDeduction, BigDecimal.ZERO) > 0) {
			for (ShoppingCart cart : cartList) {
				// 如果是赠送的商品，不均摊价格
				if (ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) {
					continue;
				}
				
				// 如果不符合商品限制，不均摊价格
				
				BigDecimal subtotal = cart.getSubtotal();
				BigDecimal buyNum = new BigDecimal(cart.getBuyNum());
				BigDecimal actualPayPrice = cart.getActualPayPrice();
				// 此商品优惠总金额
				BigDecimal useDiscountAmount = payOrderService.getUseDiscountAmount(subtotal, proTotalAmount, discountAmount);
				BigDecimal singleDiscountAmount = ArithUtil.div(useDiscountAmount, buyNum, 2);
				BigDecimal afterPayPrice = ArithUtil.sub(actualPayPrice, singleDiscountAmount, 2);
				cart.setActualPayPrice(afterPayPrice);
				cart.setActualPaySubtotal(ArithUtil.sub(cart.getActualPaySubtotal(), useDiscountAmount, 2));
			}
		}
		
		/*// 均摊每款商品所使用的红包金额
		if (redPacketDeduction.compareTo(new BigDecimal(0.00)) > 0) {
			if (cartParam.getIsRedPacketDedByAll()) {
				for (ShoppingCart cart : cartList) {
					BigDecimal subtotal = cart.getSubtotal();
					BigDecimal subtotalRatio = ArithUtil.div(subtotal, proTotalAmount, 2);
					BigDecimal useRedPacketAmount = ArithUtil.mul(subtotalRatio, redPacketDeduction, 2);
					cart.setUseRedPacketAmount(useRedPacketAmount);
					cart.setActualPaySubtotal(ArithUtil.sub(cart.getActualPaySubtotal(), useRedPacketAmount, 2));
				}
			} else {
				for (ShoppingCart cart : cartList) {
					BigDecimal buyNum = new BigDecimal(cart.getBuyNum());
					BigDecimal actualPayPrice = cart.getActualPayPrice();
					BigDecimal disAmount = cartParam.getLimitDisMap(cart.getId());
					cart.setUseRedPacketAmount(disAmount);
					if (disAmount.compareTo(new BigDecimal(0.00)) > 0) {
						BigDecimal singleDisAmount = ArithUtil.div(disAmount, buyNum, 2);
						BigDecimal afterPayPrice = ArithUtil.sub(actualPayPrice, singleDisAmount, 2);
						cart.setActualPayPrice(afterPayPrice);
						cart.setActualPaySubtotal(ArithUtil.sub(cart.getActualPaySubtotal(), disAmount, 2));
					}
				}
			}
		}*/
	}
	
	/**
	 * @description : 计算红包抵扣
	 * @author : wuhaijun
	 * @date : 2017年5月3日 上午9:48:19
	 */
	private void computeRedPacketDeduction(List<ShoppingCart> cartList, CartParam cartParam, Map<String, Object> map) throws CustomException {
		/*
		 * i. 现金红包：满足条件的商品，按商品小计的比例分摊优惠金额。
		 * ii. 单品折扣券：满足条件的商品，按小计金额最大的一个来计算，并分摊到该商品。 
		 * iii. 订单折扣券：满足条件的商品，按折扣分摊到每个符合条件的商品中。
		 */
		if (cartParam.getIsAgent() || cartParam.getUseRedPacketId() == null) {
			return;
		}
		
		// 获取红包对象
		RedPacket redPacket = redPacketService.findById(cartParam.getUseRedPacketId());
		if (redPacket == null) {
			throw new CustomException(ErrorCode.RED_PACKET_NULL.getCode(), "该红包不存在");
		}
		
		// 红包是否过期
		String currTime = DateUtils.getCurrentDateTime();
		if (currTime.compareTo(redPacket.getStartTime()) < 0 || currTime.compareTo(redPacket.getEndTime()) > 0 || !redPacket.getStatus().equals(RedPackStatus.UNUSED)) {
			log.info("该红包规则不可用，红包ID为:{}，会员ID为:{},该红包已失效", redPacket.getId(), cartParam.getBuyerId());
			throw new CustomException(ErrorCode.REDPACKET_INVALID.getCode(), "该红包已失效");
		}
		
		// 获取该红包规则
		RuleSet ruleSet = ruleSetMapper.queryRuleSetById(redPacket.getUseRuleId());
		
		// 验证红包使用规则
		CheckRuleSetParam checkRuleSetParam = new CheckRuleSetParam(cartParam.getBuyerId(), cartParam.getSysId(), ruleSet, CheckRuleSetParam.USE_1);
		checkRuleSetParam.setCurrentTime(currTime);
		checkRuleSetParam.setShoppingCartList(cartList);
		CheckRuleSetResult checkRuleSetResult = ruleSetService.checkRuleSet(checkRuleSetParam);
		if (!(CheckRuleSetResult.YES_1.equals(checkRuleSetResult.getIsCanUse()))) {
			log.info("该红包规则不可用，红包ID为:{}，会员ID为:{},错误信息{}", redPacket.getId(), cartParam.getBuyerId(),
					checkRuleSetResult.getErrorCode().getCode() + checkRuleSetResult.getErrorCode().getMessage());
			throw new CustomException(checkRuleSetResult.getErrorCode());
		}
		
		cartParam.setUseRedPacketName(ruleSet.getShowName());
		
		// 符合规则的限制商品
		Map<String, BigDecimal> limitProMap = checkRuleSetResult.getLimitProMap();
		// 符合限制总金额
		BigDecimal totalAmount = (limitProMap == null || limitProMap.get("totalAmount") == null) ? BigDecimal.ZERO : limitProMap.get("totalAmount");
		
		// 现金
		if (ShowType.CASH.toString().equals(ruleSet.getShowType())) {
			cartParam.setRedPacketDeduction(redPacket.getAmountOrDiscount());
			cartParam.setDiscountAmount(ArithUtil.add(cartParam.getDiscountAmount(), redPacket.getAmountOrDiscount(), 2));
			/*// 折后商品总价
			BigDecimal dedProTotalAmount = ArithUtil.sub(cartParam.getDedProTotalAmount(), redPacket.getAmountOrDiscount(), 2);
			if (dedProTotalAmount.compareTo(new BigDecimal(0.00)) < 0) {
				dedProTotalAmount = new BigDecimal(0.00);
			}
			cartParam.setDedProTotalAmount(dedProTotalAmount);*/
		}
		
		// 订单打折 和 单品折扣
		if (ShowType.ORDER_DISCOUNT.toString().equals(ruleSet.getShowType()) || ShowType.SINGLE_PRO_DISCOUNT.toString().equals(ruleSet.getShowType())) {
			
			cartParam.setRedPacketDeduction(this.getSubAmount(totalAmount, redPacket.getAmountOrDiscount()));
			cartParam.setDiscountAmount(ArithUtil.add(cartParam.getDiscountAmount(), cartParam.getRedPacketDeduction(), 2));
		}
		
		// 计算分摊
		// this.computeShare(cartList, cartParam);
		
		// 单件商品所使用的优惠金额=(商品小计/商品总计)*优惠金额/购买数量
		// 优惠后的支付价格=支付价格-单件商品所使用的优惠金额
		
		// 红包抵扣
		BigDecimal redPacketDeduction = cartParam.getRedPacketDeduction();
		
		// 红包金额大于0
		if (ArithUtil.compareTo(redPacketDeduction, new BigDecimal(0.00)) <= 0) {
			return;
		}
		
		// 红包金额大于符合商品的总金额，则抵扣金额=符合商品的总金额
		if (ArithUtil.compareTo(redPacketDeduction, totalAmount) > 0) {
			redPacketDeduction = totalAmount;
			cartParam.setRedPacketDeduction(redPacketDeduction);
		}
		
		// 均摊红包 支付价格
		for (ShoppingCart cart : cartList) {
			// 如果是赠送的商品，不均摊价格
			if (ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) {
				continue;
			}
			
			// 如果不符合商品限制，不均摊价格
			if (limitProMap == null || limitProMap.get(cart.getProSku()) == null) {
				continue;
			}
			
			// 如果均摊商品的小计等于零，不均摊
			/*if (ArithUtil.compareTo(limitProMap.get(cart.getProSku()), new BigDecimal(0.00)) == 0) {
				continue;
			}*/
			// 实际支付小计
			BigDecimal actualPaySubtotal = limitProMap.get(cart.getProSku());
			// 购买数量
			BigDecimal buyNum = new BigDecimal(cart.getBuyNum());
			// 此商品优惠总金额
			BigDecimal useDiscountAmount = payOrderService.getUseDiscountAmount(actualPaySubtotal, totalAmount, redPacketDeduction);
			cart.setActualPaySubtotal(ArithUtil.sub(cart.getActualPaySubtotal(), useDiscountAmount, 2));
			// 实际支付=小计 / 数量
			BigDecimal actualPayPrice = ArithUtil.div(cart.getActualPaySubtotal(), buyNum, 4);
			cart.setActualPayPrice(actualPayPrice);
			cart.setUseRedPacketAmount(useDiscountAmount);
		}
		// 折后商品总计
		cartParam.setDedProTotalAmount(ArithUtil.sub(cartParam.getDedProTotalAmount(), redPacketDeduction));
		
	}
	
	/**
	 * 获取每个快递免邮商品和商品重量小计
	 *
	 * @Title: getFreightProMap 
	 * @author: wuyicheng
	 * @date: 2017年8月10日上午10:08:01 
	 * @param cartParam 购物车参数
	 * @param cartList 购物车商品
	 * @param ruleSet 购物车规则
	 * @param limitProMap 符合限制的商品
	 * @param noFreightMethod 免邮的方式
	 * @return: void
	 * @throws
	 */
	private void getFreightProMap(CartParam cartParam, List<ShoppingCart> cartList, RuleSet ruleSet, Map<String, BigDecimal> limitProMap, Set<String> noFreightMethod) {
		// 符合限制的商品空
		if (limitProMap == null) {
			return;
		}
		
		// 购物车空
		if (cartList == null || cartList.size() <= 0) {
			return;
		}
		
		// 免邮商品
		Map<String, String> freightProMap = cartParam.getFreightProMap();
		if (freightProMap == null) {
			freightProMap = new HashMap<>();
		}
		
		// String payTypeDelivery = ruleSet.getFreeShippingPayType() + ruleSet.getFreeShippingExpressCode();
		
		// 购物车商品，赠品的总量小计
		Map<String, BigDecimal> weightProMap = new HashMap<>();
		
		// 整单免邮&&无符合的商品
		if (ShowType.FREE_SHIPPING_ORDER.toString().equals(ruleSet.getFreeShippingType()) && (limitProMap == null || limitProMap.size() <= 0)) {
			return;
		}
		
		// 遍历所有正常商品，修改订单商品总重量
		for (ShoppingCart cart : cartList) {
			
			// 获取每款商品对应的总重量
			if (weightProMap.get(cart.getProSku()) == null) {
				weightProMap.put(cart.getProSku(), ArithUtil.mul(new BigDecimal(cart.getBuyNum()), cart.getWeight()));
			} else {
				weightProMap.put(cart.getProSku(), ArithUtil.add(weightProMap.get(cart.getProSku()), ArithUtil.mul(new BigDecimal(cart.getBuyNum()), cart.getWeight(), 2), 2));
			}
			
			// 部分商品免邮
			if (ShowType.FREE_SHIPPING_PRODUCT.toString().equals(ruleSet.getFreeShippingType())) {
				// 扣除相对应免邮的商品的重量
				if (limitProMap.get(cart.getProSku()) == null) {
					continue;
				}
			}
			this.addNoFreightPro(freightProMap, noFreightMethod, cart.getProSku());
		}
		
		// 遍历所有赠品，修改订单商品总重量
		if (cartParam.getGiftList() != null && cartParam.getGiftList().size() > 0) {
			for (Gift gift : cartParam.getGiftList()) {
				
				// 获取每款商品对应的总重量
				if (weightProMap.get(gift.getProSku()) == null) {
					weightProMap.put(gift.getProSku(), ArithUtil.mul(new BigDecimal(gift.getGiftNum()), gift.getWeight()));
				} else {
					weightProMap.put(gift.getProSku(), ArithUtil.add(weightProMap.get(gift.getProSku()), ArithUtil.mul(new BigDecimal(gift.getGiftNum()), gift.getWeight(), 2), 2));
				}
				
				// 赠品符合限制
				if (ShowType.FREE_SHIPPING_PRODUCT.toString().equals(ruleSet.getFreeShippingType())) {
					// 赠品符合限制
					if (limitProMap.get(gift.getProSku()) == null) {
						continue;
					}
				}
				
				this.addNoFreightPro(freightProMap, noFreightMethod, gift.getProSku());
			}
		}
		cartParam.setWeightProMap(weightProMap);
		cartParam.setFreightProMap(freightProMap);
		
	}
	
	/** 
	 * 将购物车商品添加到对应的免邮快递方式
	 * 
	 * @Title: addNoFreightPro 
	 * @author: wuyicheng
	 * @date: 2017年8月9日下午10:05:08 
	 * @param freightProMap 快递方式对应的免邮商品
	 * @param noFreightMethod 规则免邮的方式
	 * @param proSku 当前商品
	 * @return: void
	 * @throws 
	 */
	private void addNoFreightPro(Map<String, String> freightProMap, Set<String> noFreightMethod, String proSku) {
		if (noFreightMethod != null && !noFreightMethod.isEmpty()) {
			
			if (freightProMap == null) {
				freightProMap = new HashMap<>();
			}
			
			// 遍历所有免邮方式
			for (String method : noFreightMethod) {
				// 获取这个规则需要扣除的商品sku
				String limitSku = freightProMap.get(method);
				if (StringUtil.isNotBlank(limitSku)) {
					if (StringUtil.isContains(proSku, limitSku, ConstantsUtil.COMMA)) {
						// 如果商品已经在免邮中，不重复添加
						continue;
					}
					StringBuffer limitPro = new StringBuffer();
					limitPro.append(limitSku).append(ConstantsUtil.COMMA).append(proSku);
					freightProMap.put(method, limitPro.toString());
				} else {
					freightProMap.put(method, proSku);
				}
			}
		}
		
	}
	
	/**
	 * 组装规则免邮的快递方式和付款方式
	 *
	 * @Title: buildFreightProMap 
	 * @author: wuyicheng
	 * @date: 2017年8月9日下午9:31:29 
	 * @param payTypes 支付方式
	 * @param expressCodes 派送方式
	 * @return
	 * @return: Map<String,String>
	 * @throws
	 */
	private Set<String> buildFreightProMap(String payTypes, String expressCodes) {
		Set<String> noFreightMethod = new LinkedHashSet<String>();
		// 免邮的配送方式
		List<String> payTypeList = Arrays.asList(payTypes.split(ConstantsUtil.COMMA));
		// 免邮的快递方式
		List<String> expressCodeList = Arrays.asList(expressCodes.split(ConstantsUtil.COMMA));
		
		for (String payType : payTypeList) {
			for (String expressCode : expressCodeList) {
				noFreightMethod.add(payType + expressCode);
			}
		}
		return noFreightMethod;
	}
	
	/**
	 * 购物车结算逻辑
	 *
	 * @Title: calculateShoppingCart 
	 * @author: wuyicheng
	 * @date: 2017年7月18日下午5:40:44 
	 * @param cartParam
	 * @param map
	 * @param shoppingCartList
	 * @return
	 * @throws CustomException
	 * @throws
	 */
	@Override
	public Map<String, Object> calculateShoppingCart(CartParam cartParam, Map<String, Object> map, List<ShoppingCart> shoppingCartList) throws CustomException {
		
		MemberAccount memberAccount = memberAccountService.findByMemberIdAndSysId(cartParam.getBuyerId(), cartParam.getSysId());
		if (memberAccount == null) {
			throw new CustomException(ErrorCode.MEMBER_ACCOUNT_NOT_EXIST);
		}
		
		// 判断会员是否禁用
		if (memberAccountService.filterMemberStatus(memberAccount, null)) {
			throw new CustomException(ErrorCode.MEMBER_IS_FREEZE);
		}
		
		// 购物车无商品
		if (shoppingCartList == null || shoppingCartList.size() < 1) {
			throw new CustomException(ErrorCode.NO_MATCH_COMMODITY.getCode(), "无商品可结算");
		}
		
		// 帐号剩余积分
		cartParam.setRemainIntegral(memberAccount.getTotalIntegral());
		
		// 会员等级
		MemberLevel memberLevel = memberLevelService.findByMemberIdAndSysId(cartParam.getBuyerId(), cartParam.getSysId());
		if (memberLevel == null) {
			throw new CustomException(ErrorCode.MEMBER_LEVEL_IS_NULL);
		}
		
		if (MemberLevel.Agent_LEVEL_V13.equals(memberLevel.getLever())) {
			cartParam.setIsAgent(true);
		}
		if (memberLevel.getIntegralMultiple() == null) {
			memberLevel.setIntegralMultiple(BigDecimal.ZERO);
		}
		
		// EMS不支持货到付款
		if (PayType.CASH_DELIVERY.toString().equals(cartParam.getPayMethodCode()) && OrderInfo.SHIP_EMS.equals(cartParam.getDeliveryMethodCode())) {
			log.info("下单异常：会员{},错误原因{}", "EMS不支持货到付款", ErrorCode.EMS_NO_CASH_DELIVERY.getCode() + ErrorCode.EMS_NO_CASH_DELIVERY.getMessage());
			throw new CustomException(ErrorCode.EMS_NO_CASH_DELIVERY.getCode(), "EMS不支持货到付款");
		}
		
		// 收货地址
		DeliveryAddress deliveryAddress = null;
		if (cartParam.getReceiveAddrId() != null) {
			deliveryAddress = deliveryAddressService.findById(cartParam.getReceiveAddrId());
			if (deliveryAddress == null) {
				throw new CustomException(ErrorCode.NO_SHIPPING_ADDRESS.getCode(), "收货地址不存在");
			}
			cartParam.setProvinceCode(deliveryAddress.getProvinceCode());
		}
		cartParam.setDeliveryAddress(deliveryAddress);
		
		// 购物车规则顺序
		
		// 1.特价
		// 组装购物车详情
		this.shoppingCartDetail(cartParam, shoppingCartList, memberLevel);
		
		// 2.积分：积分商品可以按比例抵扣商品金额（50积分=1元）
		this.calculateIntegral(cartParam, map, shoppingCartList);
		
		// 3. 返现余额： i. 醉品：无
		
		// 积分商品不参与购物车规则
		// 4. 购物车规则（减金额 送积分 送余额 免邮 送红包 送抽奖 送商品）
		this.shoppingCartRuleSet(cartParam, shoppingCartList, map);
		
		// 5.红包
		// 获取满足购物车条件的红包，初始化结算页面
		List<RedPacketVo> redPacketList = this.getCartRedPacket(shoppingCartList, cartParam);
		map.put("redPacketList", redPacketList);
		
		// 添加默认红包(不使用红包&&购物车没有选中红包)
		if (!(CartParam.IS_USE_RED_NO_1.equals(cartParam.getIsUseRedPacket())) && cartParam.getUseRedPacketId() == null) {
			if (redPacketList != null && redPacketList.size() > 0) {
				// 获取第一个可用红包
				RedPacketVo redPacketVo = redPacketList.get(0);
				if (redPacketVo != null && RedPacketVo.IS_CAN_USE_YES_1.equals(redPacketVo.getIsCanUse())) {
					cartParam.setUseRedPacketId(redPacketList.get(0).getId());
				}
			}
		}
		
		// 使用红包 && 无禁用红包，计算均摊
		if (!(CartParam.IS_USE_RED_NO_1.equals(cartParam.getIsUseRedPacket())) && !(CartParam.IS_DISABLE_YES_1.equals(cartParam.getIsDisableRedpacket()))) {
			// 计算红包抵扣
			this.computeRedPacketDeduction(shoppingCartList, cartParam, map);
		}
		
		// 6. 计算邮费
		this.getFreightInfo(cartParam, shoppingCartList, map);
		
		// 将赠送商品放入礼品列表
		this.addGiftAndRemoveShoppingCart(cartParam, shoppingCartList);
		
		// 实际支付总额
		BigDecimal actualPayTotalAmount = ArithUtil.add(cartParam.getDedProTotalAmount(), cartParam.getFreight(), 2);
		actualPayTotalAmount = ArithUtil.add(actualPayTotalAmount, cartParam.getAmountToIntegral(), 2);
		cartParam.setActualPayTotalAmount(actualPayTotalAmount);
		
		// 积分转成余额的金额
		BigDecimal integralToAmount = ArithUtil.div(new BigDecimal(cartParam.getTotalIntegral()), new BigDecimal(ConstantsUtil.ONE_TO_FIFTH), 2);
		// 计算成长值得总价（积分折后总计 + 积分商品总计）
		BigDecimal giveGrowthPrice = ArithUtil.add(cartParam.getDedProTotalAmount(), integralToAmount, 2);
		// 订单金额=（商品折后总价+积分商品总价） * 比例
		Integer growthValue = memberAccountService.getGrowthValue(giveGrowthPrice, memberLevel);
		cartParam.setGrowthValue(growthValue);
		
		this.buildSettleMap(cartParam, map, shoppingCartList);
		return map;
	}
	
	/**
	 * 积分使用均摊
	 *
	 * @Title: calculateIntegral 
	 * @author: wuyicheng
	 * @date: 2017年8月8日下午8:26:41 
	 * @param cartParam
	 * @param map
	 * @param shoppingCartList
	 * @return: void
	 * @throws
	 */
	private void calculateIntegral(CartParam cartParam, Map<String, Object> map, List<ShoppingCart> shoppingCartList) {
		
		int integralProNums = cartParam.getIntegralProNums();// 积分商品种类
		// 如果没有积分商品不计算
		if (integralProNums <= 0) {
			return;
		}
		Integer totalIntegeral = cartParam.getTotalIntegral() == null ? 0 : cartParam.getTotalIntegral();
		Integer remainPoints = cartParam.getRemainIntegral() == null ? 0 : cartParam.getRemainIntegral();
		
		// （1） 当结算页面有积分商品时才会出现积分抵扣行，没有积分商品不显示
		if (cartParam.getIsExistIntegralPro() == null || !(CartParam.IS_EXIST_YES_1.equals(cartParam.getIsExistIntegralPro()))) {
			cartParam.setIsExistIntegralPro(CartParam.IS_EXIST_NO_0);
			cartParam.setUseTotalIntegral(0);
			
		}
		
		// （2） 当0＜积分值<≤50时，默认不抵扣，不可勾选使用抵扣，文字显示规则为：“共XX积分，满50积分可使用”，如下：
		if (remainPoints > 0 && remainPoints <= 50) {
			cartParam.setIsUseIntegral(CartParam.IS_USE_INTEGRAL_NO_0);
			cartParam.setUseTotalIntegral(0);
		}
		Integer useTotalIntegral = 0;// 抵扣的积分
		Integer noUseTotalIntegral = totalIntegeral;// 不抵扣的积分
		// 使用账户积分
		if (CartParam.IS_USE_INTEGRAL_YES_1.equals(cartParam.getIsUseIntegral())) {
			
			// （3） 当50≤积分值≤积分总价（应付的积分总额）时，默认要抵扣，点击可以关闭不抵扣，文字显示规则为：“共XX积分，可用XX积分，还需支付XX元抵扣XX积分”，如下：
			if (remainPoints >= 50 && remainPoints <= totalIntegeral) {
				useTotalIntegral = (remainPoints / 50) * 50;
				noUseTotalIntegral = totalIntegeral - useTotalIntegral;
			}
			// 抵扣规则参照（5），其中XX元为需要补的差额。
			// （4） 当积分值≥积分总价（即积分足额抵扣）时，默认要抵扣，点击可以关闭不抵扣，文字显示规则为：“共xx积分，可足额抵扣”，如下：
			if (remainPoints > totalIntegeral) {
				useTotalIntegral = totalIntegeral;
				noUseTotalIntegral = 0;
			}
		}
		cartParam.setUseTotalIntegral(useTotalIntegral);
		BigDecimal amountToIntegral = ArithUtil.div(new BigDecimal(noUseTotalIntegral), new BigDecimal(ConstantsUtil.ONE_TO_FIFTH), 2);
		cartParam.setAmountToIntegral(amountToIntegral);
		// （5） 当积分不够抵扣，那么按照50积分的比例进行抵扣，不足50积分不抵扣（也就是说积分抵扣一定是50的整倍数）
		// 不够抵扣的部分，可以用现金补足差额，计算公式：
		// 差额=（总分总额-已抵扣积分）/50
		// 举例：商品总额为1710+46000积分，如果用户只有17890积分，那么可以抵扣的积分为17850，那么需要补的差额=（46000-17850）/50=563元。再加上1710元，才是客户最终应付金额。
		// （6） 当积分足够抵扣，那么就按照实际积分进行抵扣
		
		Integer remainShareIntegral = useTotalIntegral;// 剩余可均摊积分
		BigDecimal remainShareAmount = amountToIntegral;// 剩余可均摊金额
		// 剩余可均摊的积分和金额小于零，不均摊
		if (ArithUtil.compareTo(remainShareAmount, BigDecimal.ZERO) <= 0 && remainShareIntegral <= 0) {
			return;
		}
		for (ShoppingCart shoppingCart : shoppingCartList) {
			if (!ShoppingCart.INTEGRAL_PRO_YES_1.equals(shoppingCart.getIsIntegralPro())) {
				continue;
			}
			integralProNums--;
			// 是否只最后一个积分商品,或者均摊的值等于当前可均摊积分
			if (integralProNums == 0) {
				shoppingCart.setActualPayIntegralSum(remainShareIntegral);
				shoppingCart.setActualPayIntegral(ArithUtil.div(new BigDecimal(remainShareIntegral), new BigDecimal(shoppingCart.getBuyNum()), 2));
				
				// ====均摊价格======
				shoppingCart.setActualPaySubtotal(remainShareAmount);
				shoppingCart.setActualPayPrice(ArithUtil.div(remainShareAmount, new BigDecimal(shoppingCart.getBuyNum()), 4));
				
				break;
			} else {
				// 商品积分
				Integer sub = payOrderService
						.getUseDiscountAmount(new BigDecimal(shoppingCart.getIntegralSubtotal()), new BigDecimal(totalIntegeral), new BigDecimal(useTotalIntegral)).intValue();
				// 单个商品积分
				BigDecimal singleProIntegral = ArithUtil.div(new BigDecimal(sub), new BigDecimal(shoppingCart.getBuyNum()), 2);
				remainShareIntegral = remainShareIntegral - sub;
				shoppingCart.setActualPayIntegral(singleProIntegral);
				shoppingCart.setActualPayIntegralSum(sub);
				
				// ====均摊价格======
				BigDecimal proSub = payOrderService.getUseDiscountAmount(new BigDecimal(shoppingCart.getIntegralSubtotal()), new BigDecimal(totalIntegeral), amountToIntegral);
				// 单个商品积分
				BigDecimal singleProPrice = ArithUtil.div(proSub, new BigDecimal(shoppingCart.getBuyNum()), 4);
				remainShareAmount = ArithUtil.sub(remainShareAmount, proSub);
				shoppingCart.setActualPaySubtotal(proSub);
				shoppingCart.setActualPayPrice(singleProPrice);
			}
			
		}
	}
	
	/** 
	 * 构建结算信息
	 * 
	 * @Title: buildMap 
	 * @author: wuyicheng
	 * @date: 2017年8月8日下午3:44:41 
	 * @param cartParam
	 * @param map
	 * @param shoppingCartList
	 * @return: void
	 * @throws 
	 */
	private void buildSettleMap(CartParam cartParam, Map<String, Object> map, List<ShoppingCart> shoppingCartList) {
		map.put("actualPayTotalAmount", cartParam.getActualPayTotalAmount());
		// 赠品
		map.put("giftList", cartParam.getGiftList());
		// 购物车数据
		map.put("cartList", shoppingCartList);
		// 购物车优惠金额
		map.put("useRuleSum", cartParam.getUseRuleDiscountSum());
		// 商品总额(折前)
		map.put("proTotalAmount", cartParam.getProTotalAmount());
		// 商品总额(折后)
		map.put("dedProTotalAmount", cartParam.getDedProTotalAmount());
		// 订单总重量
		map.put("totalWeight", cartParam.getTotalWeight());
		// 红包抵扣
		map.put("redPacketDeduction", cartParam.getRedPacketDeduction());
		map.put("redPacketName", cartParam.getUseRedPacketName());
		// 会员剩余积分
		map.put("remainIntegral", cartParam.getRemainIntegral());
		// 积分补差金额
		map.put("amountToIntegral", cartParam.getAmountToIntegral());
		// 使用总积分
		map.put("useTotalIntegral", cartParam.getUseTotalIntegral());
		// 积分总数
		map.put("totalIntegral", cartParam.getTotalIntegral());
		// 是否存在积分商品
		map.put("isExistIntegralPro", cartParam.getIsExistIntegralPro());
		// 赠送成长值
		map.put("growthValue", cartParam.getGrowthValue());
		
	}
	
	/**
	 * 购物车规则
	 *
	 * @Title: shoppingCartRuleSet 
	 * @author: wuyicheng
	 * @date: 2017年7月18日下午5:13:46 
	 * @param cartParam
	 * @param shoppingCartList
	 * @param map
	 * @throws CustomException
	 * @return: void
	 * @throws
	 */
	@Override
	public void shoppingCartRuleSet(CartParam cartParam, List<ShoppingCart> shoppingCartList, Map<String, Object> map) throws CustomException {
		
		// 查询可用
		List<RuleSet> ruleSetList = this.getRuleList(cartParam.getSysId(), cartParam.getDevice(), Status.ALR_ENABLE.toString(), null, RuleType.CART, null, RuleSet.YES.toString());
		if (ruleSetList == null) {
			return;
		}
		String currentTime = DateUtils.getCurrentDateTime();
		// 使用规则集合
		List<UseRuleSetVo> useRuleSetList = cartParam.getUseRuleSetList();
		if (useRuleSetList == null) {
			useRuleSetList = new ArrayList<>();
		}
		
		// 是否禁用红包
		Short isDisableRedpacket = cartParam.getIsDisableRedpacket();
		for (RuleSet ruleSet : ruleSetList) {
			
			CheckRuleSetParam checkRuleSetParam = new CheckRuleSetParam(cartParam.getBuyerId(), cartParam.getSysId(), ruleSet, CheckRuleSetParam.USE_1);
			checkRuleSetParam.setCurrentTime(currentTime);
			checkRuleSetParam.setDevice(cartParam.getDevice());
			checkRuleSetParam.setShoppingCartList(shoppingCartList);
			checkRuleSetParam.setDeliveryMethodCode(cartParam.getDeliveryMethodCode());
			checkRuleSetParam.setPayMethodCode(cartParam.getPayMethodCode());
			checkRuleSetParam.setUseRedPacketId(cartParam.getUseRedPacketId());
			CheckRuleSetResult checkRuleSetResult = ruleSetService.checkRuleSet(checkRuleSetParam);
			
			// 判断结果
			if (!(CheckRuleSetResult.YES_1.equals(checkRuleSetResult.getIsCanUse()))) {
				log.info("该购物车规则不可用，规则ID为：{}，会员ID为：{},不可用原因{}", ruleSet.getId(), cartParam.getBuyerId(), checkRuleSetResult.getErrorCode());
				continue;
			}
			
			// 当前禁用红包 && 无其他禁用红包
			if (RuleSet.YES.equals(ruleSet.getIsStopPrivilege()) && !(CartParam.IS_DISABLE_YES_1.equals(isDisableRedpacket))) {
				cartParam.setIsDisableRedpacket(CartParam.IS_DISABLE_YES_1);
				cartParam.setLimitExplain(ruleSet.getLimitExplain());
				/* 红包计算移到购物车后 
				 * // 获取可用红包列表
				List<RedPacketVo> redPacketVos = (List<RedPacketVo>) map.get("redPacketList");
				if (redPacketVos != null && redPacketVos.size() > 0) {
					// 遍历可用红包，修改状态，修改限制说明
					for (int i = 0; i < redPacketVos.size(); i++) {
						if (RedPacketVo.IS_CAN_USE_YES_1.equals(redPacketVos.get(i).getIsCanUse())) {
							redPacketVos.get(i).setIsCanUse(RedPacketVo.IS_CAN_USE_NO_0);
							redPacketVos.get(i).setRemark(ruleSet.getLimitExplain());
						}
					}
					map.put("redPacketList", redPacketVos);
				}*/
			}
			
			Map<String, BigDecimal> limitProMap = checkRuleSetResult.getLimitProMap();
			BigDecimal totalNums = (limitProMap == null || limitProMap.get("totalNums") == null) ? BigDecimal.ZERO : limitProMap.get("totalNums");// 总数量
			BigDecimal totalAmount = (limitProMap == null || limitProMap.get("totalAmount") == null) ? BigDecimal.ZERO : limitProMap.get("totalAmount");// 总金额
			
			if (ShowType.SUB_AMOUNT.toString().equals(ruleSet.getShowType()) && limitProMap != null) {
				log.info("规则ID：{},会员ID：{},限制商品{}", ruleSet.getId(), cartParam.getBuyerId(), limitProMap.toString());
			}
			
			// 使用规则赠送礼品总计
			BigDecimal giveSum = this.getGiveTotal(cartParam, ruleSet, totalNums, totalAmount);
			
			// 构建使用购物车使用规则
			this.buildUseRuleSet(cartParam, shoppingCartList, limitProMap, ruleSet, useRuleSetList, giveSum);
			
			// 是否停用其他规则
			if (RuleSet.YES.equals(ruleSet.getIsStopOtherRule())) {
				break;
			}
			
		}
		map.put("useRuleSetList", useRuleSetList);
	}
	
	/** 
	 * 将行为抽奖的赠品移到赠品列表
	 * 
	 * @Title: addGiftAndRemoveShoppingCart 
	 * @author: wuyicheng
	 * @date: 2017年7月21日下午5:00:32 
	 * @param cartParam
	 * @param shoppingCartList
	 * @return: void
	 * @throws 
	 */
	private void addGiftAndRemoveShoppingCart(CartParam cartParam, List<ShoppingCart> shoppingCartList) {
		// 赠品列表
		List<Gift> giftList = cartParam.getGiftList();
		if (giftList == null || giftList.size() <= 0) {
			giftList = new ArrayList<>();
		}
		for (int i = 0; i < shoppingCartList.size(); i++) {
			ShoppingCart shoppingCart = shoppingCartList.get(i);
			// 如果是赠品，从购物车去掉，
			if (ShoppingCart.PREMIUM_YES.equals(shoppingCart.getIsPremium())) {
				Gift gift = new Gift();
				gift.setRuleName(shoppingCart.getRuleName());
				gift.setImageUrl(shoppingCart.getImageUrl());
				gift.setProName(shoppingCart.getProName());
				gift.setProSku(shoppingCart.getProSku());
				gift.setActualPayPrice(new BigDecimal(0.00));
				if (ShoppingCart.INTEGRAL_PRO_YES_1.equals(shoppingCart.getIsIntegralPro())) {
					// 积分商品，价格取积分转换后的价格
					gift.setProPrice(shoppingCart.getPriorityPrice());
				} else {
					gift.setProPrice(shoppingCart.getFormerPrice());
				}
				gift.setGiftNum(shoppingCart.getBuyNum().intValue());
				gift.setFormerPrice(shoppingCart.getFormerPrice());
				gift.setSubtotal(new BigDecimal(0.00));
				gift.setWeight(shoppingCart.getWeight());
				gift.setBusinessType(shoppingCart.getBusinessType());
				gift.setRuleSetId(shoppingCart.getRuleId());
				gift.setCartId(shoppingCart.getId());
				gift.setIsIntegralPro(shoppingCart.getIsIntegralPro());
				gift.setIntegralPrice(0);
				giftList.add(gift);
				shoppingCartList.remove(i);
				i--;
			}
			
		}
		cartParam.setGiftList(giftList);
	}
	
	/**
	 * @throws CustomException 
	 * 构建购物车使用规则
	 *
	 * @Title: buildUseRuleSet 
	 * @author: wuyicheng
	 * @date: 2017年7月19日下午5:03:21 
	 * @param cartParam
	 * @param shoppingCartList
	 * @param limitProMap
	 * @param ruleSet
	 * @param useRuleSetList
	 * @param giveSum
	 * @return: void
	 * @throws
	 */
	private void buildUseRuleSet(CartParam cartParam, List<ShoppingCart> shoppingCartList, Map<String, BigDecimal> limitProMap, RuleSet ruleSet, List<UseRuleSetVo> useRuleSetList,
			BigDecimal giveSum) throws CustomException {
		// 添加使用规则
		UseRuleSetVo useRuleSetVo = new UseRuleSetVo();
		
		// 1.减金额
		if (ShowType.SUB_AMOUNT.toString().equals(ruleSet.getShowType()) && ArithUtil.compareTo(giveSum, BigDecimal.ZERO) > 0) {
			
			// 均摊购物车
			this.computeShareRuleAmount(shoppingCartList, ruleSet.getShowType(), giveSum, limitProMap);
			
			// 累加购物优惠金额
			cartParam.setUseRuleDiscountSum(ArithUtil.add(cartParam.getUseRuleDiscountSum(), giveSum, 2));
			
			// 减少商品折扣金额
			cartParam.setDedProTotalAmount(ArithUtil.sub(cartParam.getDedProTotalAmount(), giveSum, 2));
		}
		
		// 2.送积分
		// 3.免邮费
		if (ShowType.FREE_POSTAGE.toString().equals(ruleSet.getShowType())) {
			
			// 规则免邮的方式
			Set<String> noFreightMethod = this.buildFreightProMap(ruleSet.getFreeShippingPayType(), ruleSet.getFreeShippingExpressCode());
			String payTypeDelivery = ruleSet.getFreeShippingPayType() + ruleSet.getFreeShippingExpressCode();
			// 获取免邮商品
			this.getFreightProMap(cartParam, shoppingCartList, ruleSet, limitProMap, noFreightMethod);
			
			// 所选配送方式和快递类型不一致，则不计入免邮规则
			if (cartParam.getPayMethodCode() == null || cartParam.getDeliveryMethodCode() == null || !noFreightMethod.contains(payTypeDelivery)) {
				return;
			}
		}
		
		// 4.送充值余额
		// 5.送红包
		// 6.送商品
		if (ShowType.GIVE_PRO.toString().equals(ruleSet.getShowType())) {
			// 获取满足购物车规则的赠品
			this.getGiftList(shoppingCartList, limitProMap, cartParam, ruleSet, giveSum);
		}
		
		// 7.送抽奖次数
		useRuleSetVo.setGiveNum(giveSum);
		useRuleSetVo.setGiveRuleSetIds(ruleSet.getGiveCode());
		useRuleSetVo.setGiveTimeDot(ruleSet.getGiveTimeDot());
		useRuleSetVo.setRuleSetId(ruleSet.getId());
		useRuleSetVo.setShowName(ruleSet.getShowName());
		useRuleSetVo.setShowType(ruleSet.getShowType());
		useRuleSetVo.setGiveTimeDot(ruleSet.getGiveTimeDot());
		useRuleSetList.add(useRuleSetVo);
	}
	
	/**
	 * 均摊规则优惠金额
	 *
	 * @Title: computeShareRuleAmount 
	 * @author: wuyicheng
	 * @date: 2017年7月18日下午8:14:48 
	 * @param shoppingCartList 购物车
	 * @param showType 规则类型
	 * @param useRuleSum 
	 * @param limitProMap
	 * @return: void
	 * @throws
	 */
	private void computeShareRuleAmount(List<ShoppingCart> shoppingCartList, String showType, BigDecimal useRuleSum, Map<String, BigDecimal> limitProMap) {
		// 没有商品符合
		if (limitProMap != null && limitProMap.size() > 0) {
			// 符合规则的商品总金额
			BigDecimal totalAmount = limitProMap.get("totalAmount");
			if (ArithUtil.compareTo(totalAmount, new BigDecimal(0)) != 0) {
				for (ShoppingCart shoppingCart : shoppingCartList) {
					
					// 商品不存在跳过
					if (limitProMap.get(shoppingCart.getProSku()) == null) {
						continue;
					}
					// 实付小计
					BigDecimal subtotal = limitProMap.get(shoppingCart.getProSku());
					// 单个商品获得比例
					BigDecimal singleRuleSum = payOrderService.getUseDiscountAmount(subtotal, totalAmount, useRuleSum);
					// 拆金额
					if (ShowType.SUB_AMOUNT.toString().equals(showType)) {
						// BigDecimal singlePro = ArithUtil.div(singleRuleSum, new BigDecimal(shoppingCart.getBuyNum()), 4);
						// BigDecimal singlePrice = ArithUtil.sub(shoppingCart.getActualPayPrice(), singlePro, 4);
						shoppingCart.setUseRuleSum(ArithUtil.add(shoppingCart.getUseRuleSum(), singleRuleSum, 2));
						shoppingCart.setActualPaySubtotal(ArithUtil.sub(shoppingCart.getActualPaySubtotal(), singleRuleSum, 2));
						shoppingCart.setActualPayPrice(ArithUtil.div(shoppingCart.getActualPaySubtotal(), new BigDecimal(shoppingCart.getBuyNum()), 4));
					}
					
				}
			}
		}
	}
	
	/**
	 * 购物车赠送商品数额
	 *
	 * @Title: getGiveTotal 
	 * @author: wuyicheng
	 * @date: 2017年7月19日下午4:57:12 
	 * @param cartParam
	 * @param ruleSet
	 * @param totalNums
	 * @param totalAmount
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	private BigDecimal getGiveTotal(CartParam cartParam, RuleSet ruleSet, BigDecimal totalNums, BigDecimal totalAmount) {
		// 赠送总数
		BigDecimal giveNums = BigDecimal.ZERO;
		// 免费不用计算
		if (ShowType.FREE_POSTAGE.toString().equals(ruleSet.getShowType())) {
			return giveNums;
		}
		// 叠加次数(默认1次)
		int overlayNum = 1;
		
		// 是否叠加
		if (RuleSet.YES.equals(ruleSet.getIsOverlay())) {
			
			// 限制购买金额
			if (RuleSet.YES.equals(ruleSet.getIsLimitBuyMoney()) && ArithUtil.compareTo(ruleSet.getAmountDown(), BigDecimal.ZERO) != 0) {
				overlayNum = ArithUtil.div(totalAmount, ruleSet.getAmountDown()).intValue();
			}
			
			// 限制购买数量
			else if (RuleSet.YES.equals(ruleSet.getIsLimitBuyNum()) && ArithUtil.compareTo(ruleSet.getNumDown(), BigDecimal.ZERO) != 0) {
				overlayNum = ArithUtil.div(totalNums, ruleSet.getNumDown()).intValue();
			}
			
		}
		
		// 减金额去金额，其他规则取数量
		if (ShowType.SUB_AMOUNT.toString().equals(ruleSet.getShowType())) {
			giveNums = ArithUtil.mul(ruleSet.getAmount(), new BigDecimal(overlayNum), 2);
		} else {
			giveNums = ArithUtil.mul(ruleSet.getGiveNum(), new BigDecimal(overlayNum), 2);
		}
		
		// 优惠金额超出最大金额取最大金额
		if (ruleSet.getSingleMostNum() != null && ArithUtil.compareTo(giveNums, ruleSet.getSingleMostNum()) > 0) {
			giveNums = ruleSet.getSingleMostNum();
		}
		
		// 如果是减金额，且减的金额大于商品总额，取商品总额为优惠价
		if (ArithUtil.compareTo(giveNums, totalAmount) > 0 && ShowType.SUB_AMOUNT.toString().equals(ruleSet.getShowType())) {
			giveNums = totalAmount;
		}
		return giveNums;
	}
	
	/**
	 * 获取运费信息
	 *
	 * @Title: getFreightInfo 
	 * @author: wuyicheng
	 * @date: 2017年7月21日上午10:35:28 
	 * @param cartParam
	 * @param map
	 * @return: void
	 * @throws
	 */
	private void getFreightInfo(CartParam cartParam, List<ShoppingCart> shoppingCartList, Map<String, Object> map) {
		
		Map<String, BigDecimal> weightMap = this.calculateWeight(cartParam, shoppingCartList);
		map.put("weightProMap", cartParam.getWeightProMap());
		map.put("freightProMap", cartParam.getFreightProMap());
		map.put("weightMap", weightMap);
		// 运费
		// 后台订单接口如果已经填入运费，不再计算邮费
		if (cartParam.getBackFreight() == null) {
			// 支付方式+配送方式
			String payTypeDelivery = cartParam.getPayMethodCode() + cartParam.getDeliveryMethodCode();
			// 实付运费重量
			BigDecimal totalWeight = weightMap.get(payTypeDelivery) == null ? cartParam.getTotalWeight() : weightMap.get(payTypeDelivery);
			// 当前运费
			BigDecimal freight = this.getFreight(cartParam, cartParam.getDeliveryMethodCode(), cartParam.getPayMethodCode(), totalWeight);
			cartParam.setFreight(freight);
		} else {
			cartParam.setFreight(cartParam.getBackFreight());
		}
		map.put("freight", cartParam.getFreight());
		
		// 配送方式
		List<Map<String, Object>> deliveryMethodList = shoppingCartMapper.queryDeliveryMethod(null);
		map.put("deliveryMethodList", deliveryMethodList);
		
		// 各种配送方式对应的运费
		Map<String, Object> freights = new HashMap<>();
		for (Map<String, Object> delivery : deliveryMethodList) {
			String payType = PayType.ONLINE.toString();
			String deliveryType = delivery.get("code").toString();
			// 支付方式+配送方式
			String payTypeDelivery = payType + deliveryType;
			// 实付运费重量
			BigDecimal totalWeight = weightMap.get(payTypeDelivery) == null ? cartParam.getTotalWeight() : weightMap.get(payTypeDelivery);
			// 当前运费
			BigDecimal freight = this.getFreight(cartParam, deliveryType, payType, totalWeight);
			
			freights.put(deliveryType, freight);
		}
		// 在线支付
		map.put("onlineFreights", freights);
		
		// 货到付款对应各种配送方式对应的运费
		Map<String, Object> noPayFreights = new HashMap<>();
		for (Map<String, Object> delivery : deliveryMethodList) {
			String payType = PayType.CASH_DELIVERY.toString();
			String deliveryType = delivery.get("code").toString();
			// 支付方式+配送方式
			String payTypeDelivery = payType + deliveryType;
			// 实付运费重量
			BigDecimal totalWeight = weightMap.get(payTypeDelivery) == null ? cartParam.getTotalWeight() : weightMap.get(payTypeDelivery);
			// 当前运费
			BigDecimal freight = this.getFreight(cartParam, deliveryType, payType, totalWeight);
			
			noPayFreights.put(deliveryType, freight);
		}
		// 货到付款
		map.put("noPayFreights", noPayFreights);
		
		// 选中支付方式
		if (PayType.ONLINE.toString().equals(cartParam.getPayMethodCode())) {
			map.put("freights", freights);
		} else {
			map.put("freights", noPayFreights);
		}
		
	}
	
	/**
	 * 计算商品总重量
	 *
	 * @Title: calculateWeight 
	 * @author: wuyicheng
	 * @date: 2017年7月26日下午10:08:12 
	 * @param cartParam
	 * @param shoppingCartList
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	private Map<String, BigDecimal> calculateWeight(CartParam cartParam, List<ShoppingCart> shoppingCartList) {
		Map<String, BigDecimal> weightMap = new HashMap<>();
		// 配送方式对应限制的商品
		Map<String, String> freightProMap = cartParam.getFreightProMap();
		// 每个商品对应的总重量
		Map<String, BigDecimal> weightProMap = cartParam.getWeightProMap();
		// 循环统计每个配送方式的商品总重量
		for (String key : freightProMap.keySet()) {
			String[] skus = freightProMap.get(key).split(ConstantsUtil.COMMA);
			BigDecimal totalWeight = cartParam.getTotalWeight();
			if (skus != null && skus.length > 0) {
				for (String sku : skus) {
					totalWeight = ArithUtil.sub(totalWeight, weightProMap.get(sku));
				}
			}
			weightMap.put(key, totalWeight);
		}
		return weightMap;
	}
	
	/**
	 * 购物车详情
	 *
	 * @Title: shoppingCartDetail 
	 * @author: wuyicheng
	 * @date: 2017年7月18日下午3:27:41 
	 * @param cartParam
	 * @param shoppingCartList
	 * @param memberLevel
	 * @throws CustomException
	 * @throws
	 */
	@Override
	public void shoppingCartDetail(CartParam cartParam, List<ShoppingCart> shoppingCartList, MemberLevel memberLevel) throws CustomException {
		cartParam.setIsExistIntegralPro(CartParam.IS_EXIST_NO_0);// 默认不存在积分商品
		// 多个商品SKU，用逗号隔开
		StringBuffer cartSkus = new StringBuffer();
		int integralProNums = 0;// 积分商品的种类
		// 使用特价规则
		List<UseRuleSetVo> useRuleSetList = new ArrayList<>();
		for (ShoppingCart cart : shoppingCartList) {
			
			// 组装商品
			CartProInfo cartProInfo = this.getProInfo(cart.getProId(), cart.getProSku(), cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(),
					new BigDecimal(cart.getBuyNum()), (ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) ? true : false);
			
			// 没有其他禁用红包
			if (!(CartParam.IS_DISABLE_YES_1.equals(cartParam.getIsDisableRedpacket())) && RuleSet.YES.equals(cartProInfo.getIsStopPrivilege())) {
				cartParam.setIsDisableRedpacket(CartParam.IS_DISABLE_YES_1);
				cartParam.setLimitExplain(cartProInfo.getLimitExplain());
			}
			
			// 购物车赠品价格为零
			if (ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium()) && !CartProInfo.IS_JF_PRODUCT_YES_1.equals(cartProInfo.getIsJfProduct())) {
				cartProInfo.setPriorityPrice(new BigDecimal(0.00));
			}
			
			cartSkus.append(cartProInfo.getProSku()).append(",");
			// 判断商品是否上架，提交订单
			if (CartProInfo.IS_ON_SHELVES_NO_0.equals(cartProInfo.getIsOnShelves())) {
				throw new CustomException(ErrorCode.ON_SHELF.getCode(), "商品未上架");
			}
			cart.setImageUrl(cartProInfo.getImageUrl());
			cart.setProName(cartProInfo.getProName());
			cart.setProSku(cartProInfo.getProSku());
			cart.setWeight(cartProInfo.getWeight());
			cart.setActualPayPrice(cartProInfo.getPriorityPrice());// 实际支付价
			cart.setPriorityPrice(cartProInfo.getPriorityPrice());// 会员价
			cart.setFormerPrice(cartProInfo.getFormerPrice());// 原价
			cart.setBusinessType(cartProInfo.getBusinessType());// 自营|联营
			
			// 特价商品保存使用规则
			if (cartProInfo.getRuleSetId() != null) {
				UseRuleSetVo useRuleSetVo = new UseRuleSetVo();
				useRuleSetVo.setRuleSetId(cartProInfo.getRuleSetId());
				useRuleSetVo.setShowType(ShowType.SPECIAL_PRICE.toString());
				useRuleSetVo.setProSku(cartProInfo.getProSku());
				useRuleSetList.add(useRuleSetVo);
			}
			
			if (CartProInfo.IS_JF_PRODUCT_YES_1.equals(cartProInfo.getIsJfProduct())) {
				// 积分商品
				cart.setIsIntegralPro(ShoppingCart.INTEGRAL_PRO_YES_1);
				cart.setActualPayIntegral(BigDecimal.ZERO);
				cart.setActualPayIntegralSum(0);
				cart.setSubtotal(BigDecimal.ZERO);
				cart.setGiveIintegral(0);
				cart.setUseRuleSum(BigDecimal.ZERO);
				// 赠品是积分商品，不统计积分
				if (!ShoppingCart.PREMIUM_YES.equals(cart.getIsPremium())) {
					cart.setIntegralPrice(cartProInfo.getIntegralPrice());
					cart.setIntegralSubtotal(cartProInfo.getIntegralPrice() * cart.getBuyNum());
					cartParam.setIsExistIntegralPro(CartParam.IS_EXIST_YES_1);
					cartParam.setUseTotalIntegral(cartParam.getUseTotalIntegral() + cart.getActualPayIntegralSum());
					cartParam.setTotalIntegral(cartParam.getTotalIntegral() + cart.getIntegralSubtotal());
					integralProNums++;
				} else {
					// 赠品
					cart.setIntegralPrice(0);
					cart.setIntegralSubtotal(0);
				}
			} else {
				// 非积分商品
				cart.setIsIntegralPro(ShoppingCart.INTEGRAL_PRO_NO_0);
				cart.setActualPayIntegral(BigDecimal.ZERO);
				cart.setActualPayIntegralSum(0);
				cart.setIntegralPrice(0);
				cart.setIntegralSubtotal(0);
				cart.setUseRuleSum(BigDecimal.ZERO);
				// 实付小计(实付价 * 数量)
				BigDecimal actualPaySubtotal = ArithUtil.mul(cart.getActualPayPrice(), new BigDecimal(cart.getBuyNum()), 2);
				cart.setActualPaySubtotal(actualPaySubtotal);
				// 小计(优先价 * 数量)
				BigDecimal subtotal = ArithUtil.mul(cart.getPriorityPrice(), new BigDecimal(cart.getBuyNum()), 2);
				cart.setSubtotal(subtotal);
				// 赠送积分
				Integer giveIntegral = integralRecordService.getGiveIntegral(subtotal, memberLevel);
				cart.setGiveIintegral(giveIntegral);
				// 总积分
				cartParam.setGiveTotalIntegral(cartParam.getGiveTotalIntegral() + giveIntegral);
				// 商品总额
				BigDecimal proTotalAmount = ArithUtil.add(cartParam.getProTotalAmount(), subtotal, 2);
				cartParam.setProTotalAmount(proTotalAmount);
				cartParam.setDedProTotalAmount(proTotalAmount);
			}
			// 商品总重量
			BigDecimal subWeight = ArithUtil.mul(cart.getWeight(), new BigDecimal(cart.getBuyNum()), 4);
			BigDecimal totalWeight = ArithUtil.add(subWeight, cartParam.getTotalWeight(), 4);
			cartParam.setTotalWeight(totalWeight);
		}
		cartParam.setIntegralProNums(integralProNums);
		cartParam.setUseRuleSetList(useRuleSetList);
		if (cartSkus.toString().length() > 0) {
			cartParam.setCartSkus(cartSkus.toString().substring(0, cartSkus.toString().length() - 1));
		}
	}
	
	/**
	 * @description : 获取满足购物车条件的红包
	 * @author : wuhaijun
	 * @date : 2017年4月26日 下午5:21:47
	 */
	@Override
	public List<RedPacketVo> getCartRedPacket(List<ShoppingCart> cartList, CartParam cartParam) throws CustomException {
		
		/*if (cartParam.getIsAgent()) {
			return null;
		}*/
		
		// int cartLen = cartList.size();
		List<RedPacketVo> validRedList = new ArrayList<RedPacketVo>();
		
		// 查询未使用的红包
		RedPacket red = new RedPacket();
		red.setMemberId(cartParam.getBuyerId());
		red.setSysId(cartParam.getSysId());
		red.setStatus(RedPackStatus.UNUSED);
		List<RedPacket> redPacketList = redPacketService.findListByPage(red, null);
		
		if (redPacketList == null || redPacketList.size() < 1) {
			return null;
		}
		
		String currTime = DateUtils.getCurrentDateTime();
		// 筛选有效的红包
		for (RedPacket redPacket : redPacketList) {
			RuleSet ruleSet = ruleSetMapper.queryRuleSetById(redPacket.getUseRuleId());
			if (ruleSet == null) {
				log.info("红包规则不存在，红包ID为：" + redPacket.getId() + "，会员ID为：" + cartParam.getBuyerId());
				continue;
			}
			if (redPacket.getStartTime() == null || currTime.compareTo(redPacket.getStartTime()) < 0) {
				continue;
			}
			if (redPacket.getEndTime() == null || currTime.compareTo(redPacket.getEndTime()) > 0) {
				continue;
			}
			
			// 规则如果禁用，不显示
			if (!Status.ALR_ENABLE.toString().equals(ruleSet.getStatus())) {
				continue;
			}
			
			// 不是红包规则
			if (ruleSet.getRuleType() == null || !(RuleType.RED_PACKET.toString().equals(ruleSet.getRuleType()))) {
				continue;
			}
			
			RedPacketVo redPacketVo = new RedPacketVo();
			redPacketVo.setIsCanUse(RedPacketVo.IS_CAN_USE_YES_1);// 默认可使用
			redPacketVo.setRemark(ruleSet.getLimitExplain());
			// 特价规则限制红包
			if (CartParam.IS_DISABLE_YES_1.equals(cartParam.getIsDisableRedpacket())) {
				log.info("特价规则或者购物车规则限制使用红包，红包规则ID：{}红包ID为：{}，会员ID为：{}", redPacket.getUseRuleId(), redPacket.getId(), cartParam.getBuyerId());
				redPacketVo.setIsCanUse(RedPacketVo.IS_CAN_USE_NO_0);
				// redPacketVo.setRemark(cartParam.getLimitExplain());
			}
			
			// 验证红包规则是否可用
			CheckRuleSetParam checkRuleSetParam = new CheckRuleSetParam(cartParam.getBuyerId(), cartParam.getSysId(), ruleSet, CheckRuleSetParam.USE_1);
			checkRuleSetParam.setCurrentTime(currTime);
			checkRuleSetParam.setShoppingCartList(cartList);
			checkRuleSetParam.setDevice(cartParam.getDevice());
			CheckRuleSetResult checkRuleSetResult = ruleSetService.checkRuleSet(checkRuleSetParam);
			
			// 不符合红包规则使用条件
			if (CheckRuleSetResult.NO_0.equals(checkRuleSetResult.getIsCanUse())) {
				log.info("红包规则限制使用红包，红包ID为：{}，会员ID为：{},错误信息：{}", redPacket.getId(), cartParam.getBuyerId(),
						checkRuleSetResult.getErrorCode().getCode() + checkRuleSetResult.getErrorCode().getMessage());
				redPacketVo.setIsCanUse(RedPacketVo.IS_CAN_USE_NO_0);
			}
			
			Map<String, BigDecimal> limitProMap = checkRuleSetResult.getLimitProMap();
			// 符合商品的总金额
			BigDecimal cartProAmount = (limitProMap == null || limitProMap.get("totalAmount") == null) ? new BigDecimal(0.00) : limitProMap.get("totalAmount");
			
			redPacketVo.setId(redPacket.getId());
			redPacketVo.setName(ruleSet.getShowName());
			redPacketVo.setFullAmount(ruleSet.getFullAmountUse());
			redPacketVo.setDeadline(redPacket.getEndTime());
			if (ShowType.CASH.toString().equals(ruleSet.getShowType())) {
				// 现金
				redPacketVo.setType(RedPacketVo.TYPE_CASH_1);
				redPacketVo.setDiscount(null);
				redPacketVo.setSubAmount(redPacket.getAmountOrDiscount());
			} else if (ShowType.ORDER_DISCOUNT.toString().equals(ruleSet.getShowType())) {
				// 订单打折
				redPacketVo.setType(RedPacketVo.TYPE_ORDER_DISCOUNT_3);
				redPacketVo.setDiscount(redPacket.getAmountOrDiscount());
				redPacketVo.setSubAmount(this.getSubAmount(cartProAmount, redPacket.getAmountOrDiscount()));
			} else if (ShowType.SINGLE_PRO_DISCOUNT.toString().equals(ruleSet.getShowType())) {
				// 单品打折
				redPacketVo.setType(RedPacketVo.TYPE_SINGLE_PRO_DISCOUNT_4);
				redPacketVo.setDiscount(redPacket.getAmountOrDiscount());
				redPacketVo.setSubAmount(this.getSubAmount(cartProAmount, redPacket.getAmountOrDiscount()));
			}
			validRedList.add(redPacketVo);
		}
		
		// l 取值：显示所有在有效期内，不满足条件可用的红包，
		// l 排序：（依优惠金额由大到小排序，再依到期时间正序排序—临近到期的排前面）
		if (validRedList != null && validRedList.size() > 1) {
			Collections.sort(validRedList, new Comparator<RedPacketVo>() {
				
				public int compare(RedPacketVo o1, RedPacketVo o2) {
					// 可用在前
					if (o1.getIsCanUse().shortValue() < o2.getIsCanUse().shortValue()) {
						return 1;
					}
					
					if (o1.getIsCanUse().shortValue() == o2.getIsCanUse().shortValue()) {
						if (ArithUtil.compareTo(o1.getSubAmount(), o2.getSubAmount()) < 0) {
							return 1;
						}
						if (ArithUtil.compareTo(o1.getSubAmount(), o2.getSubAmount()) == 0) {
							return 0;
						}
						return -1;
					}
					return -1;
					
				}
				
			});
		}
		
		return validRedList;
	}
	
	/** 
	 * 根据折扣计算优惠金额
	 * 
	 * @Title: getSubAmount 
	 * @author: wuyicheng
	 * @date: 2017年7月24日上午1:45:46 
	 * @param cartProAmount
	 * @param amountOrDiscount
	 * @return
	 * @return: BigDecimal
	 * @throws 
	 */
	private BigDecimal getSubAmount(BigDecimal cartProAmount, BigDecimal amountOrDiscount) {
		// 折扣比例
		BigDecimal ratio = ArithUtil.div(amountOrDiscount, new BigDecimal(10), 6);
		// 符合商品限制的折扣商品总金额
		BigDecimal disProTotalAmount = ArithUtil.mul(cartProAmount, ratio, 2);
		// 优惠总金额
		BigDecimal subAmount = ArithUtil.sub(cartProAmount, disProTotalAmount, 2);
		// 如果优惠金额大于商品总金额，则只优惠最大金额
		if (ArithUtil.compareTo(cartProAmount, subAmount) < 0) {
			subAmount = cartProAmount;
		}
		return subAmount;
	}
	
	/**
	 * @功能描述：计算规则SKU限制金额
	 * @作者 : cjj
	 * @修改 : wuhaijun
	 * @创建时间 : 2017年5月21日下午8:42:43
	 */
	private BigDecimal computeSkuLimitAmount(RuleSet ruleSet, List<ShoppingCart> cartList, CartParam cartParam) {
		if (StringUtils.isBlank(ruleSet.getSku())) {
			return cartParam.getProTotalAmount();
		}
		BigDecimal cartProAmount = new BigDecimal(0.00);
		for (ShoppingCart cart : cartList) {
			if (ruleSet.getSku().contains(cart.getProSku())) {
				cartProAmount = ArithUtil.add(cartProAmount, cart.getSubtotal(), 2);
			}
		}
		return cartProAmount;
	}
	
	/**
	 * @description : 计算运费（未使用 2017-07-03）
	 * @author : wuhaijun
	 * @date : 2017年4月26日 下午4:34:35
	 */
	private void computeFreight(CartParam cartParam) {
		// 商品总量，把克转为千克
		BigDecimal totalWeight = ArithUtil.div(cartParam.getTotalWeight(), new BigDecimal(1000), 4);
		// 商品总重量为0或者配送方式未选择时，运费为0
		if (totalWeight.compareTo(new BigDecimal(0.0000)) == 0 || StringUtils.isBlank(cartParam.getDeliveryMethodCode())) {
			return;
		}
		// 选择货到付款，未选择收货地址时，运费为0
		if (PayType.CASH_DELIVERY.toString().equals(cartParam.getPayMethodCode()) && cartParam.getReceiveAddrId() == null) {
			return;
		}
		
		BigDecimal totalFreight = BigDecimal.ZERO;
		if (PayType.CASH_DELIVERY.toString().equals(cartParam.getPayMethodCode())) {// 货到付款
			// 货到付款 申通快递、顺丰快递依【模板】计算出运费打8折
			totalFreight = this.calculateFreight(cartParam.getProvinceCode(), cartParam.getDeliveryMethodCode(), totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_8);
			
		} else {
			if (cartParam.getDedProTotalAmount().compareTo(new BigDecimal(59.00)) < 0) {
				
				// 在线支付低于59元，依【模板】计算运费；
				totalFreight = this.calculateFreight(cartParam.getProvinceCode(), cartParam.getDeliveryMethodCode(), totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_10);
				
			} else {
				// 在线支付大于等于59元，申通快递、EMS包邮；顺丰快递依运费模板打8折
				if ("ship_sf".equals(cartParam.getDeliveryMethodCode())) {// 顺丰
					totalFreight = this.calculateFreight(cartParam.getProvinceCode(), cartParam.getDeliveryMethodCode(), totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_8);
				} else {
					totalFreight = BigDecimal.ZERO;
				}
			}
			
		}
		
		// 运费
		cartParam.setFreight(totalFreight);
	}
	
	/**
	 * 计算运费
	 *
	 * @Title: calculateFreight 
	 * @author: wuyicheng
	 * @date: 2017年7月26日下午10:04:48 
	 * @date: 2017年7月3日上午9:51:32 
	 * @param provinceCode 省编码
	 * @param deliveryMethodCode 配送方式CODE 
	 * @param totalWeight 总重 
	 * @param totalFreightDiscount 运费折扣 
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	private BigDecimal calculateFreight(String provinceCode, String deliveryMethodCode, BigDecimal totalWeight, BigDecimal totalFreightDiscount) {
		BigDecimal totalFreight = BigDecimal.ZERO;
		// 收货省份为空，则运费为零
		if (StringUtil.isBlank(provinceCode)) {
			return totalFreight;
		}
		// 查询运费模板
		Map<String, Object> freightTemplateMap = shoppingCartMapper.queryFreightTemplate(provinceCode, deliveryMethodCode);
		// 首重
		BigDecimal firstHeavy = new BigDecimal(freightTemplateMap.get("firstHeavy").toString());
		// 续重
		BigDecimal contiunedHeavy = new BigDecimal(freightTemplateMap.get("contiunedHeavy").toString());
		if (totalWeight.compareTo(new BigDecimal(1.0000)) <= 0) {
			totalFreight = firstHeavy;
		} else {
			// 商品总重量-1千克，然后向上取整
			BigDecimal tempWeight = ArithUtil.sub(totalWeight, new BigDecimal(1.0000), 4).setScale(0, BigDecimal.ROUND_UP);
			BigDecimal tempfreight = ArithUtil.mul(tempWeight, contiunedHeavy, 2);
			totalFreight = ArithUtil.add(tempfreight, firstHeavy, 2);
		}
		totalFreight = ArithUtil.mul(totalFreightDiscount, totalFreight, 2);
		return totalFreight;
	}
	
	/**
	 * 计算运费
	 *
	 * @Title: getFreight 
	 * @author: wuyicheng
	 * @date: 2017年7月18日下午3:26:52 
	 * @param cartParam
	 * @param delivery
	 * @param payMethod
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	@Override
	public BigDecimal getFreight(CartParam cartParam, String delivery, String payMethod, BigDecimal totalWeight) {
		// 商品总量，把克转为千克
		totalWeight = ArithUtil.div(totalWeight, new BigDecimal(1000), 4);
		
		// 商品总重量为0时，运费为0
		if (totalWeight.compareTo(BigDecimal.ZERO) == 0) {
			return BigDecimal.ZERO;
		}
		// 选择货到付款，未选择收货地址时，运费为0
		if (PayType.CASH_DELIVERY.toString().equals(payMethod) && cartParam.getReceiveAddrId() == null) {
			return BigDecimal.ZERO;
		}
		
		BigDecimal totalFreight = BigDecimal.ZERO;
		if (PayType.CASH_DELIVERY.toString().equals(payMethod)) {// 货到付款
			
			// 货到付款 申通快递、顺丰快递依【模板】计算出运费打8折
			totalFreight = this.calculateFreight(cartParam.getProvinceCode(), delivery, totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_8);
			
		} else {
			if (cartParam.getDedProTotalAmount().compareTo(ConstantsUtil.NO_FREIGHT_59) < 0) {
				
				// 在线支付低于59元，依【模板】计算运费；
				totalFreight = this.calculateFreight(cartParam.getProvinceCode(), delivery, totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_10);
				
			} else {
				// 在线支付大于等于59元，申通快递、EMS包邮；顺丰快递依运费模板打8折
				if (OrderInfo.SHIP_SF.equals(delivery)) {// 顺丰
					totalFreight = this.calculateFreight(cartParam.getProvinceCode(), delivery, totalWeight, ConstantsUtil.FREIGHT_DISCOUNT_8);
				} else {
					totalFreight = BigDecimal.ZERO;
				}
			}
			
		}
		return totalFreight;
	}
	
	/**
	 * @description : 库存不足或者没有库存返回false，多个商品库存校验
	 * @author : wuhaijun
	 * @date : 2017年5月2日 上午11:30:11
	 */
	public boolean checkStock(String proNo, BigDecimal buyNum, Map<String, Map<String, Object>> returnMap) {
		Map<String, Object> proStockMap = returnMap.get(proNo);
		BigDecimal validStock = new BigDecimal(proStockMap.get("validStock").toString());
		if (buyNum.compareTo(validStock) > 0) {
			return false;
		}
		return true;
	}
	
	/**
	 * @description : 库存不足或者没有库存返回false，单个商品库存查询
	 * @author : wuhaijun
	 * @throws CustomException
	 * @date : 2017年4月27日 下午8:59:45
	 */
	private boolean checkStock(String proSku, BigDecimal buyNum) throws CustomException {
		Map<String, Map<String, Object>> returnMap = this.findCisBranchStockByProSkus(proSku);
		Map<String, Object> proStockMap = returnMap.get(proSku);
		BigDecimal validStock = new BigDecimal(proStockMap.get("validStock").toString());
		if (buyNum.compareTo(validStock) > 0) {
			return false;
		}
		return true;
	}
	
	/**
	 * @description : 根据商品SKU查询商品分仓库存,支持一个或者多个SKU,多个用英文逗号隔开
	 * @return data : 如下 { "SKU001": { "validStock": 100.0000 }, "SKU002": { "validStock": 150.0000 }, }
	 * @author : wuhaijun
	 * @date : 2017年4月27日 下午9:00:00
	 */
	public Map<String, Map<String, Object>> findCisBranchStockByProSkus(String proSkus) throws CustomException {
		Map<String, Map<String, Object>> returnMap = new HashMap<String, Map<String, Object>>();
		
		StringBuffer url = new StringBuffer();
		url.append(findBranchStockUrl).append("&proNo=").append(proSkus);
		
		String cisResult = null;
		try {
			cisResult = HttpUtil.get(url.toString(), null, 30000, 30000);
		} catch (Exception e) {
			throw new CustomException(ErrorCode.STORAGE_REQUEST_FAILED.getCode(), "库存请求失败");
		}
		log.info("同步cis库存返回值:" + cisResult);
		
		JSONObject returnParam = JSONObject.fromObject(cisResult);
		if (returnParam.getBoolean("success") == false) {
			throw new CustomException(ErrorCode.STORAGE_INFO_BACK_FAILED.getCode(), "库存信息返回失败");
		}
		
		JSONArray pros = returnParam.getJSONArray("stockInfo");
		if (pros == null || pros.size() < 1) {
			throw new CustomException(ErrorCode.NO_STORAGE_INFO.getCode(), "无库存信息");
		}
		
		int proLen = pros.size();
		for (int i = 0; i < proLen; i++) {
			// 正常库存
			BigDecimal normalStock = new BigDecimal(0.0000);
			// 残次库存
			BigDecimal imperfectStock = new BigDecimal(0.0000);
			// 在途库存
			BigDecimal transitStock = new BigDecimal(0.0000);
			// 生产库存
			BigDecimal produceStock = new BigDecimal(0.0000);
			// 拆分库存
			BigDecimal splitStock = new BigDecimal(0.0000);
			// 供应商库存
			BigDecimal supplierStock = new BigDecimal(0.0000);
			// 订单预占
			BigDecimal orderPreholding = new BigDecimal(0.0000);
			// 领料预占
			BigDecimal pickPreholding = new BigDecimal(0.0000);
			// 调拨预占
			BigDecimal allotPreholding = new BigDecimal(0.0000);
			// 退供预占
			BigDecimal backPreholding = new BigDecimal(0.0000);
			// 盘点预占
			BigDecimal checkPreholding = new BigDecimal(0.0000);
			// 虚拟预占
			BigDecimal virtualPreholding = new BigDecimal(0.0000);
			
			JSONObject pro = pros.getJSONObject(i);
			String proSku = pro.getString("proNo");
			
			if (pro.has("inventDisableQty") && pro.get("inventDisableQty") != null) {
				virtualPreholding = ArithUtil.add(virtualPreholding, new BigDecimal(pro.get("inventDisableQty").toString()), 4);
			}
			
			if (pro.has("supplierStock") && pro.get("supplierStock") != null) {
				supplierStock = ArithUtil.add(supplierStock, new BigDecimal(pro.get("supplierStock").toString()), 4);
			}
			
			JSONArray repertoryInfos = pro.getJSONArray("repertoryInfo");
			if (repertoryInfos != null && repertoryInfos.size() > 0) {
				int repLen = repertoryInfos.size();
				for (int k = 0; k < repLen; k++) {
					JSONObject repertoryInfo = repertoryInfos.getJSONObject(k);
					
					if (repertoryInfo.has("normalQty") && repertoryInfo.get("normalQty") != null) {
						normalStock = ArithUtil.add(normalStock, new BigDecimal(repertoryInfo.get("normalQty").toString()), 4);
					}
					
					if (repertoryInfo.has("defetiveQty") && repertoryInfo.get("defetiveQty") != null) {
						imperfectStock = ArithUtil.add(imperfectStock, new BigDecimal(repertoryInfo.get("defetiveQty").toString()), 4);
					}
					
					if (repertoryInfo.has("transitQty") && repertoryInfo.get("transitQty") != null) {
						transitStock = ArithUtil.add(transitStock, new BigDecimal(repertoryInfo.get("transitQty").toString()), 4);
					}
					
					if (repertoryInfo.has("produceStock") && repertoryInfo.get("produceStock") != null) {
						produceStock = ArithUtil.add(produceStock, new BigDecimal(repertoryInfo.get("produceStock").toString()), 4);
					}
					
					if (repertoryInfo.has("splitStock") && repertoryInfo.get("splitStock") != null) {
						splitStock = ArithUtil.add(splitStock, new BigDecimal(repertoryInfo.get("splitStock").toString()), 4);
					}
					
					if (repertoryInfo.has("orderPrehold") && repertoryInfo.get("orderPrehold") != null) {
						orderPreholding = ArithUtil.add(orderPreholding, new BigDecimal(repertoryInfo.get("orderPrehold").toString()), 4);
					}
					
					if (repertoryInfo.has("pickPrehold") && repertoryInfo.get("pickPrehold") != null) {
						pickPreholding = ArithUtil.add(pickPreholding, new BigDecimal(repertoryInfo.get("pickPrehold").toString()), 4);
					}
					
					if (repertoryInfo.has("allocatPrehold") && repertoryInfo.get("allocatPrehold") != null) {
						allotPreholding = ArithUtil.add(allotPreholding, new BigDecimal(repertoryInfo.get("allocatPrehold").toString()), 4);
					}
					
					if (repertoryInfo.has("backPrehold") && repertoryInfo.get("backPrehold") != null) {
						backPreholding = ArithUtil.add(backPreholding, new BigDecimal(repertoryInfo.get("backPrehold").toString()), 4);
					}
					
					if (repertoryInfo.has("inventoryPrehold") && repertoryInfo.get("inventoryPrehold") != null) {
						checkPreholding = ArithUtil.add(checkPreholding, new BigDecimal(repertoryInfo.get("inventoryPrehold").toString()), 4);
					}
				}
			}
			
			// 有效库存
			BigDecimal validStock = ArithUtil.sub(normalStock, virtualPreholding, 4);
			validStock = ArithUtil.sub(validStock, orderPreholding, 4);
			validStock = ArithUtil.sub(validStock, pickPreholding, 4);
			validStock = ArithUtil.sub(validStock, allotPreholding, 4);
			validStock = ArithUtil.sub(validStock, backPreholding, 4);
			validStock = ArithUtil.sub(validStock, checkPreholding, 4);
			validStock = ArithUtil.add(validStock, produceStock, 4);
			validStock = ArithUtil.add(validStock, splitStock, 4);
			validStock = ArithUtil.add(validStock, supplierStock, 4);
			
			Map<String, Object> proStockMap = new HashMap<String, Object>();
			proStockMap.put("validStock", validStock);
			returnMap.put(proSku, proStockMap);
		}
		
		return returnMap;
	}
	
	/**
	 * 不能购买的商品 --库存不足
	 * 
	 * @Description:
	 * @Title:
	 * @author:
	 * @date: 2017年5月18日下午12:00:21
	 */
	public String jugeCanBuy(Long memberId, Long sysId) throws CustomException {
		List<ShoppingCart> shops = shoppingCartMapper.query(memberId, sysId);
		List<String> proSkuList = new ArrayList<String>();
		Map<Long, String> proIdMap = new HashMap<Long, String>();
		for (ShoppingCart s : shops) {
			ProductInfo pro = productInfoService.selectById(s.getProId());
			proSkuList.add(pro.getProSku());
			proIdMap.put(s.getProId(), pro.getProSku());
		}
		String skuStr = proSkuList.toString().substring(1, proSkuList.toString().length() - 1);
		Map<String, Map<String, Object>> map = this.findCisBranchStockByProSkus(skuStr.replaceAll(" ", ""));
		List<String> notBuyList = new ArrayList<String>();
		for (ShoppingCart s : shops) {
			Map<String, Object> proStockMap = map.get(proIdMap.get(s.getProId()));
			BigDecimal validStock = new BigDecimal(proStockMap.get("validStock").toString());
			BigDecimal buyNum = new BigDecimal(s.getBuyNum());
			if (buyNum.compareTo(validStock) > 0) {
				notBuyList.add(proIdMap.get(s.getProId()));
			}
		}
		return notBuyList.toString();
	}
	
	@Override
	public List<ShoppingCart> queryBySettle(String[] ids, Long buyerId, Long sysId) {
		return shoppingCartMapper.queryBySettle(ids, buyerId, sysId);
	}
	
	/**
	 * 构建虚拟购物车 @Title: createVirtualShoppingCart @author: wuyicheng @date: 2017年6月14日上午11:00:44 @param orderDetails @return @throws
	 */
	@Override
	public List<ShoppingCart> createVirtualShoppingCart(List<BackOrderDetailVo> orderDetails, Long memberId, Long sysId) {
		List<ShoppingCart> shoppingCartList = new ArrayList<>();
		for (BackOrderDetailVo backOrderDetailVo : orderDetails) {
			// 组装非赠品
			if (!(BackOrderDetailVo.IS_GIVE_PRO_YES_1.equals(backOrderDetailVo.getIsGivePro()))) {
				ShoppingCart shoppingCart = new ShoppingCart();
				shoppingCart.setBuyerId(memberId);
				shoppingCart.setBuyNum(backOrderDetailVo.getProductNum().intValue());
				shoppingCart.setProSku(backOrderDetailVo.getProSku());
				shoppingCart.setSysId(sysId);
				shoppingCart.setSubtotal(backOrderDetailVo.getSubTotal());
				shoppingCartList.add(shoppingCart);
			}
		}
		return shoppingCartList;
	}
	
	/**
	 * 重新购买订单里面的商品
	 */
	@Override
	public Result<OrderBuyAgainVo> buyAgain(FrontOrderVo frontOrderVo, Boolean flag) throws CustomException {
		
		// 返回的数据
		OrderBuyAgainVo resultVo = new OrderBuyAgainVo();
		
		// 未上架或者库存为0的 数据
		List<ImgAndTitlePro> data = new ArrayList<ImgAndTitlePro>();
		
		resultVo.setPros(data);
		
		// 成功加入购物车返回的IDS
		List<String> ids = new ArrayList<>();
		
		// result pros里面保存着不能购买的商品列表信息
		Result<OrderBuyAgainVo> result = new Result<OrderBuyAgainVo>();
		result.setData(resultVo);
		
		// 1.获取订单商品列表的所有sku
		List<String> skus = new ArrayList<>();
		List<FrontOrderDetailVo> odetails = frontOrderVo.getOdetail();
		// 2.遍历商品详情把sku加入到 skus集合中
		for (FrontOrderDetailVo f : odetails) {
			skus.add(f.getProSku());
		}
		
		// 3.getInfo 获取商品标题 主图imgurl 库存 return List<Map<String,Object>>
		List<Map<String, Object>> list = proExtInfoService.findProExtList(skus, frontOrderVo.getDevice(), frontOrderVo.getSysId());
		
		// map: key value
		// title 产品标题
		// mainImgUrl 主图地址
		// stock 库存
		// status
		// 遍历集合
		
		// 订单里的商品数量
		int count = list.size();
		// 可购买
		int canBuyCount = 0;
		
		List<FrontOrderDetailVo> frontOrderDetailVoS = frontOrderVo.getOdetail();
		
		for (Map<String, Object> map : list) {
			String title = (String) map.get(TITLE);
			String proSku = (String) map.get(PRO_SKU);
			String mainImgUrl = "";
			if (map.get(IMG_URL) != null) {
				mainImgUrl = (String) map.get(IMG_URL);
			}
			
			String statu = (String) map.get(STATE);
			
			// 获取商品库存Map集
			Map<String, Map<String, Object>> products = productInfoService.getStock(proSku);
			// 获取Sku对应的有效库存Map
			Map<String, Object> validstocks = products.get(proSku);
			BigDecimal stockNum = (BigDecimal) validstocks.get("validStock");
			int validStock = 0;
			if (null != stockNum) {
				validStock = stockNum.intValue();
			}
			
			// 已上架有库存可购买的商品(库存不足时 购买数量为库存的数量)
			if (statu.equals(ProductExtInfo.ON_SHELF) && validStock > 0) {
				// 实际购买数量
				int buyNum = frontOrderVo.getFrontOrderDetailVo(proSku).getBuyNum().intValue();
				canBuyCount++;
				if (buyNum >= validStock) {
					buyNum = validStock;
				}
				// 是否执行加入购物车动作
				if (flag) {
					FrontOrderDetailVo detailVo = frontOrderVo.getFrontOrderDetailVo(proSku);
					CartParam cartParam = new CartParam();
					cartParam.setProId(detailVo.getProId());
					cartParam.setBuyerId(frontOrderVo.getBuyerId());
					
					cartParam.setBuyNum(buyNum);
					
					cartParam.setDevice(frontOrderVo.getDevice());
					cartParam.setSysId(frontOrderVo.getSysId());
					cartParam.setAddTime(DateUtils.getCurrentDateTime());
					
					// 开始执行加入购物车
					
					CartProInfo cartProInfo = this.getProInfo(cartParam.getProId(), null, cartParam.getSysId(), cartParam.getBuyerId(), cartParam.getDevice(), BigDecimal.ZERO,
							false);
					cartParam.setActualPayPrice(cartProInfo.getPriorityPrice());
					// 查询该商品是否存在于购物车
					ShoppingCart formerSc = shoppingCartMapper.queryExist(cartParam);
					System.out.println(ids);
					cartParam.setIsPremium(ShoppingCart.PREMIUM_NO);
					if (formerSc == null) {// 新增
						
						shoppingCartMapper.newAdd(cartParam);
						ids.add(cartParam.getId().toString());
					} else {// 累加
						shoppingCartMapper.upAdd(cartParam);
						ids.add(formerSc.getId().toString());
					}
					
					// 把成功加入购物车的ID返回
					System.out.println(cartParam);
					result.setErrorCode(ErrorCode.SUCCESS);
					result.setMessage("成功加入购物车");
					
				}
			} else {
				
				// false带回不能购买的商品列表
				if (!flag) {
					// 把不能购买的对象创建并加入集合中
					ImgAndTitlePro v = new ImgAndTitlePro();
					v.setMainImgUrl(mainImgUrl);
					v.setTitle(title);
					data.add(v);
				}
			}
			
		}
		
		// 执行加入购物车动作结束之后
		if (flag) {
			// 把购物车id返回
			resultVo.setIds(StringUtils.join(ids, ","));
			result.setErrorCode(ErrorCode.SUCCESS);
			result.setMessage("成功加入购物车");
			return result;
		}
		
		if (canBuyCount == 0) {
			result.setErrorCode(ErrorCode.COUNTEMPTY_OR_NOSAL);
			result.setMessage("订单中的商品都卖光啦，再看看其他商品吧");
			return result;
		}
		if (canBuyCount == count) {
			
			// 把购物车id返回
			String idsStr = Arrays.toString(ids.toArray());
			resultVo.setIds(idsStr.substring(1, idsStr.length() - 1));
			result.setErrorCode(ErrorCode.SUCCESS);
			result.setMessage("成功加入购物车");
			return result;
		}
		
		// 把购物车id返回
		String idsStr = Arrays.toString(ids.toArray());
		resultVo.setIds(idsStr.substring(1, idsStr.length() - 1));
		result.setErrorCode(ErrorCode.PART_ENOUGH);
		result.setMessage("以下商品库存不足，先将其他有货商品加入购物车?");
		return result;
	}
	
	/**
	 * 新增赠品
	 * @param skus
	 * @param sysId
	 * @param memberId
	 * @param buyNum
	 */
	public void addPremium(List<String> skus, Long sysId, Long memberId, BigDecimal buyNum, Long ruleId, String ruleName) {
		if (skus != null && skus.size() > 0 && buyNum != null && buyNum.intValue() > 0) {
			for (int i = 0; i < skus.size(); i++) {
				ProductInfo pi = productInfoService.getProBySku(skus.get(i));
				if (pi != null) {
					CartParam cartParam = new CartParam();
					cartParam.setBuyerId(memberId);
					cartParam.setProId(pi.getId());
					cartParam.setIsPremium(ShoppingCart.PREMIUM_YES);
					cartParam.setSysId(sysId);
					cartParam.setRuleId(ruleId);
					ShoppingCart formerSc = shoppingCartMapper.queryPremiumExist(cartParam);
					cartParam.setActualPayPrice(new BigDecimal(0));
					// Integer num = buyNum.intValue() + (formerSc == null ? 0 : formerSc.getBuyNum());
					cartParam.setBuyNum(buyNum.intValue());
					cartParam.setAddTime(DateUtils.getCurrentDateTime());
					cartParam.setRuleName(ruleName);
					if (formerSc == null) {// 新增
						shoppingCartMapper.newAdd(cartParam);
					} else {// 累加
						shoppingCartMapper.upAdd(cartParam);
					}
				}
			}
		}
		
	}
	
	private final static String validStockStr = "validStock";
	
	/**
	 * 验证商品的
	  *  @Title: validateProduct
	  * @author joy.zhang
	  * @date 2017年8月9日 下午5:55:20
	  * @param cart
	  * @param cartProInfo
	  * @return int  0 正常   1数量校验失败 2失效 
	 */
	public int validateProduct(ShoppingCart cart, CartProInfo cartProInfo, Map<String, Map<String, Object>> returnMap) {
		int res = 0;
		// 1.判断商品库存=0，则商品显示失效；
		// 2.判断商品的最低起批量>库存量时，则商品显示失效；
		// 3.判断商品状态为“未上架”，则商品显示失效；
		// 4.判断商品在购物车数量超出最高购买量，则在商品标题下标注：“超出最高购买量”
		// 5.判断商品在购物车数量低于最低购买量，则在商品标题下标注：“低于最低购买量”
		// 6.判断商品在购物车的数量大于库存量，并且库存不为0，则在商品标题下标注：“库存不足”
		// 7.当最低起购量>库存量，或最高起购量<最低购量，则在购物车中显示为失效商品
		Map<String, Object> proStockMap = returnMap.get(cartProInfo.getProSku());
		Integer validStock = 0;
		if (proStockMap != null && proStockMap.get(validStockStr) != null) {
			validStock = new BigDecimal(proStockMap.get(validStockStr).toString()).intValue();
		}
		Integer buyLowLimit = cartProInfo.getBuyLowLimit() == null ? 0 : cartProInfo.getBuyLowLimit();
		Integer buyUpperLimit = cartProInfo.getBuyUpperLimit() == null ? 0 : cartProInfo.getBuyUpperLimit();
		
		// 商品库存=0,商品库存 < 1
		if (validStock < 1) {
			res = 2;
			return res;
		}
		
		// 最低起批量>库存量
		if (buyLowLimit > 0 && buyLowLimit > validStock) {
			res = 2;
			return res;
		}
		
		// 商品未上架
		if (CartProInfo.IS_ON_SHELVES_NO_0.equals(cartProInfo.getIsOnShelves())) {
			res = 2;
			cart.setLimitMsg("商品未上架");
			return res;
		}
		// 最高起购量<最低购量，则在购物车中显示为失效商品
		if (buyLowLimit > 0 && buyUpperLimit > 0 && buyUpperLimit < buyLowLimit) {
			res = 2;
			return res;
		}
		// 超出最高购买量
		if (buyUpperLimit > 0 && cart.getBuyNum() > buyUpperLimit) {
			res = 1;
			cart.setLimitMsg("超出最高购买量");
			return res;
		}
		// 低于最低购买量
		if (buyLowLimit > 0 && cart.getBuyNum() < buyLowLimit) {
			res = 1;
			cart.setLimitMsg("低于最低购买量");
			return res;
		}
		// 库存不足
		if (validStock > 0 && !checkStock(cartProInfo.getProSku(), new BigDecimal(cart.getBuyNum()), returnMap)) {
			res = 1;
			cart.setLimitMsg("库存不足");
			return res;
			
		}
		
		return res;
	}
	
	/**
	 * 获得购物车商品库存数
	  *  @Title: getSkuStockMap
	  * @author joy.zhang
	  * @date 2017年8月9日 下午9:49:17
	  * @param cartList
	  * @return
	  * @throws CustomException
	  * @return Map<String,Map<String,Object>>
	 */
	private Map<String, Map<String, Object>> getSkuStockMap(List<ShoppingCart> cartList) throws CustomException {
		// 检验库存
		Map<String, Map<String, Object>> returnMap = new HashMap<String, Map<String, Object>>();
		StringBuilder cartSkus = new StringBuilder();
		if (cartList != null && cartList.size() > 0) {
			JSONObject params = new JSONObject();
			// for (ShoppingCart cart : cartList) {
			for (int i = 0; i < cartList.size(); i++) {
				ShoppingCart cart = cartList.get(i);
				params.put("proId", cart.getProId());
				params.put("sysId", cart.getSysId());
				ProductExtInfo pro = proExtInfoService.selectByProId(params);
				if (pro != null) {
					cartSkus.append(pro.getProSku()).append(",");
				}
			}
			String strSkus = cartSkus.toString();
			if (StringUtil.isNotBlank(strSkus)) {
				strSkus = strSkus.substring(0, strSkus.length() - 1);
			}
			returnMap = this.findCisBranchStockByProSkus(strSkus);
		}
		return returnMap;
		
	}
	
}